@oracle-agent/oracle 0.14.1 → 0.15.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.
Files changed (447) hide show
  1. package/README.md +2 -2
  2. package/SETUP.md +4 -4
  3. package/dist/action-receipts.mjs +1 -0
  4. package/dist/action-semantics.mjs +1 -0
  5. package/dist/address-book.mjs +2 -0
  6. package/dist/bin/desk-server.mjs +59 -0
  7. package/dist/bin/oracle-data-mcp.mjs +8 -0
  8. package/dist/bin/oracle-equities.mjs +20 -0
  9. package/dist/bin/oracle-init.mjs +24 -0
  10. package/dist/bin/oracle-public-server.mjs +5 -0
  11. package/dist/bin/oracle-route.mjs +22 -0
  12. package/dist/bin/oracle-scan.mjs +18 -0
  13. package/dist/bin/oracle-upgrade.mjs +21 -0
  14. package/dist/bin/oracle.mjs +61 -0
  15. package/dist/chains.mjs +1 -0
  16. package/dist/cli/commands/auth.mjs +16 -0
  17. package/dist/cli/commands/bootstrap.mjs +18 -0
  18. package/dist/cli/commands/chain.mjs +21 -0
  19. package/dist/cli/commands/chat.mjs +45 -0
  20. package/dist/cli/commands/credential.mjs +1 -0
  21. package/dist/cli/commands/data-mcp.mjs +2 -0
  22. package/dist/cli/commands/data.mjs +12 -0
  23. package/dist/cli/commands/doctor.mjs +5 -0
  24. package/dist/cli/commands/equities.mjs +15 -0
  25. package/dist/cli/commands/farm.mjs +59 -0
  26. package/dist/cli/commands/fees.mjs +10 -0
  27. package/dist/cli/commands/follow.mjs +28 -0
  28. package/dist/cli/commands/harness.mjs +15 -0
  29. package/dist/cli/commands/help.mjs +1 -0
  30. package/dist/cli/commands/init.mjs +3 -0
  31. package/dist/cli/commands/mcp.mjs +36 -0
  32. package/dist/cli/commands/model.mjs +54 -0
  33. package/dist/cli/commands/plugins.mjs +43 -0
  34. package/dist/cli/commands/prepare.mjs +2 -0
  35. package/dist/cli/commands/public.mjs +3 -0
  36. package/dist/cli/commands/resolve.mjs +23 -0
  37. package/dist/cli/commands/route.mjs +2 -0
  38. package/dist/cli/commands/runner.mjs +1 -0
  39. package/dist/cli/commands/scan.mjs +2 -0
  40. package/dist/cli/commands/setup.mjs +34 -0
  41. package/dist/cli/commands/sign.mjs +4 -0
  42. package/dist/cli/commands/signer.mjs +1 -0
  43. package/dist/cli/commands/swap.mjs +36 -0
  44. package/dist/cli/commands/upgrade.mjs +2 -0
  45. package/dist/cli/commands/vault.mjs +1 -0
  46. package/dist/cli/commands/version.mjs +2 -0
  47. package/dist/data/desk-data.mjs +55 -0
  48. package/dist/data/names.mjs +2 -0
  49. package/dist/data/providers/farming.mjs +2 -0
  50. package/dist/equities/index.mjs +1 -0
  51. package/dist/index.mjs +60 -0
  52. package/dist/nft-gas-war-guard.mjs +1 -0
  53. package/dist/onboarding/harness-configs.mjs +4 -0
  54. package/dist/portfolio-risk.mjs +1 -0
  55. package/dist/prepare-envelope.mjs +1 -0
  56. package/dist/public-api/agent-grants.mjs +3 -0
  57. package/dist/public-control/policy-schema.mjs +1 -0
  58. package/dist/router/index.mjs +2 -0
  59. package/dist/scanner/index.mjs +4 -0
  60. package/dist/signals/index.mjs +1 -0
  61. package/dist/watch-preferences.mjs +1 -0
  62. package/package.json +32 -78
  63. package/public/oracle-splash/_variants/ice.html +5 -18
  64. package/public/oracle-splash/_variants/ivory.html +5 -18
  65. package/public/oracle-splash/index.html +114 -34
  66. package/CONTRIBUTING.md +0 -99
  67. package/bin/desk-server.mjs +0 -473
  68. package/bin/oracle-data-mcp.mjs +0 -1252
  69. package/bin/oracle-equities.mjs +0 -168
  70. package/bin/oracle-init.mjs +0 -525
  71. package/bin/oracle-public-server.mjs +0 -36
  72. package/bin/oracle-route.mjs +0 -254
  73. package/bin/oracle-scan.mjs +0 -192
  74. package/bin/oracle-upgrade.mjs +0 -42
  75. package/bin/oracle.mjs +0 -34
  76. package/docs/adding-a-chain.md +0 -229
  77. package/docs/architecture.md +0 -139
  78. package/docs/buzz-integration.md +0 -115
  79. package/docs/cli.md +0 -143
  80. package/docs/connectors.md +0 -13
  81. package/docs/hyperliquid-builder-code.md +0 -50
  82. package/docs/locals-only-fee-waiver.md +0 -34
  83. package/docs/oracle-pack-standard.md +0 -29
  84. package/docs/profiles.md +0 -151
  85. package/docs/public-surface.md +0 -206
  86. package/examples/add-a-chain.mjs +0 -65
  87. package/examples/oracle-pack-template.mjs +0 -38
  88. package/examples/research-a-token.mjs +0 -70
  89. package/plugins/oracle-owner-gate/__init__.py +0 -288
  90. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  91. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  92. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  93. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  94. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  95. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  96. package/scripts/adversarial-bench.mjs +0 -114
  97. package/scripts/build-dist.mjs +0 -119
  98. package/scripts/build-inscription.py +0 -230
  99. package/scripts/check-doc-drift.mjs +0 -123
  100. package/scripts/check-test-count.mjs +0 -105
  101. package/scripts/e2e-hl-markets.mjs +0 -21
  102. package/scripts/e2e-hl-perps.mjs +0 -48
  103. package/scripts/e2e-hypercore-staking.mjs +0 -128
  104. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  105. package/scripts/guard-publish.mjs +0 -22
  106. package/scripts/protocol-template-gate.mjs +0 -15
  107. package/scripts/public-api-scan.mjs +0 -23
  108. package/scripts/publish-dist.mjs +0 -67
  109. package/scripts/record-hero-cli.sh +0 -80
  110. package/scripts/secret-scan.mjs +0 -169
  111. package/scripts/smoke-dist-bins.mjs +0 -89
  112. package/scripts/verify-dist.mjs +0 -29
  113. package/scripts/verify-v3-venues.mjs +0 -233
  114. package/skins/oracle.yaml +0 -56
  115. package/src/action-receipts.mjs +0 -265
  116. package/src/action-semantics.mjs +0 -62
  117. package/src/address-book.mjs +0 -208
  118. package/src/agent-auth.mjs +0 -206
  119. package/src/approval-guard.mjs +0 -282
  120. package/src/attestation-secret.mjs +0 -94
  121. package/src/audit-log.mjs +0 -196
  122. package/src/auth/oauth.mjs +0 -672
  123. package/src/auto-slippage.mjs +0 -378
  124. package/src/capability-posture.mjs +0 -125
  125. package/src/cards.mjs +0 -422
  126. package/src/chains.mjs +0 -62
  127. package/src/cli/chain-catalog.mjs +0 -215
  128. package/src/cli/chain-state.mjs +0 -74
  129. package/src/cli/commands/auth.mjs +0 -193
  130. package/src/cli/commands/bootstrap.mjs +0 -87
  131. package/src/cli/commands/chain.mjs +0 -143
  132. package/src/cli/commands/chat.mjs +0 -465
  133. package/src/cli/commands/credential.mjs +0 -9
  134. package/src/cli/commands/data-mcp.mjs +0 -18
  135. package/src/cli/commands/data.mjs +0 -75
  136. package/src/cli/commands/doctor.mjs +0 -136
  137. package/src/cli/commands/equities.mjs +0 -41
  138. package/src/cli/commands/farm.mjs +0 -129
  139. package/src/cli/commands/fees.mjs +0 -109
  140. package/src/cli/commands/follow.mjs +0 -130
  141. package/src/cli/commands/harness.mjs +0 -63
  142. package/src/cli/commands/help.mjs +0 -7
  143. package/src/cli/commands/init.mjs +0 -27
  144. package/src/cli/commands/mcp.mjs +0 -154
  145. package/src/cli/commands/model.mjs +0 -106
  146. package/src/cli/commands/plugins.mjs +0 -275
  147. package/src/cli/commands/prepare.mjs +0 -12
  148. package/src/cli/commands/public.mjs +0 -20
  149. package/src/cli/commands/resolve.mjs +0 -64
  150. package/src/cli/commands/route.mjs +0 -12
  151. package/src/cli/commands/runner.mjs +0 -9
  152. package/src/cli/commands/scan.mjs +0 -12
  153. package/src/cli/commands/setup.mjs +0 -294
  154. package/src/cli/commands/sign.mjs +0 -21
  155. package/src/cli/commands/signer.mjs +0 -9
  156. package/src/cli/commands/swap.mjs +0 -102
  157. package/src/cli/commands/upgrade.mjs +0 -12
  158. package/src/cli/commands/vault.mjs +0 -9
  159. package/src/cli/commands/version.mjs +0 -22
  160. package/src/cli/first-run.mjs +0 -23
  161. package/src/cli/kernel.mjs +0 -262
  162. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  163. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  164. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  165. package/src/cli/mcp-targets/codex.mjs +0 -41
  166. package/src/cli/mcp-targets/cursor.mjs +0 -32
  167. package/src/cli/mcp-targets/shared.mjs +0 -71
  168. package/src/cli/mcp-targets/vscode.mjs +0 -39
  169. package/src/cli/messaging-platforms.mjs +0 -217
  170. package/src/cli/model-config.mjs +0 -78
  171. package/src/cli/operator-dispatch.mjs +0 -194
  172. package/src/cli/oracle-harness.py +0 -415
  173. package/src/cli/paths.mjs +0 -107
  174. package/src/cli/runtime.mjs +0 -351
  175. package/src/cli/setup-state.mjs +0 -168
  176. package/src/cli/spawn-child.mjs +0 -43
  177. package/src/data/catalog.mjs +0 -858
  178. package/src/data/desk-data.mjs +0 -877
  179. package/src/data/http.mjs +0 -253
  180. package/src/data/names.mjs +0 -188
  181. package/src/data/provider-endpoint.mjs +0 -94
  182. package/src/data/providers/aave-v3.mjs +0 -139
  183. package/src/data/providers/across-bridge.mjs +0 -41
  184. package/src/data/providers/aerodrome.mjs +0 -245
  185. package/src/data/providers/aevo.mjs +0 -33
  186. package/src/data/providers/approval-indexer.mjs +0 -133
  187. package/src/data/providers/approvals.mjs +0 -594
  188. package/src/data/providers/babylon-staking.mjs +0 -149
  189. package/src/data/providers/balancer.mjs +0 -209
  190. package/src/data/providers/beefy-yields.mjs +0 -45
  191. package/src/data/providers/birdeye-tokens.mjs +0 -33
  192. package/src/data/providers/bisq-markets.mjs +0 -145
  193. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  194. package/src/data/providers/bitcoin-meta.mjs +0 -378
  195. package/src/data/providers/blockscout.mjs +0 -14
  196. package/src/data/providers/bob-rootstock.mjs +0 -198
  197. package/src/data/providers/braiins-insights.mjs +0 -103
  198. package/src/data/providers/bridge-aggregator.mjs +0 -259
  199. package/src/data/providers/bridges.mjs +0 -242
  200. package/src/data/providers/bungee.mjs +0 -29
  201. package/src/data/providers/celestia-da.mjs +0 -38
  202. package/src/data/providers/changenow.mjs +0 -135
  203. package/src/data/providers/compound.mjs +0 -32
  204. package/src/data/providers/connext.mjs +0 -28
  205. package/src/data/providers/convex.mjs +0 -30
  206. package/src/data/providers/cow-protocol.mjs +0 -110
  207. package/src/data/providers/cowswap.mjs +0 -415
  208. package/src/data/providers/curve.mjs +0 -201
  209. package/src/data/providers/das-assets.mjs +0 -59
  210. package/src/data/providers/debridge.mjs +0 -109
  211. package/src/data/providers/defillama.mjs +0 -88
  212. package/src/data/providers/dexscreener.mjs +0 -43
  213. package/src/data/providers/drift.mjs +0 -32
  214. package/src/data/providers/dydx.mjs +0 -41
  215. package/src/data/providers/evm-rpc.mjs +0 -225
  216. package/src/data/providers/farming.mjs +0 -291
  217. package/src/data/providers/geckoterminal.mjs +0 -34
  218. package/src/data/providers/gmx.mjs +0 -496
  219. package/src/data/providers/hiro-stacks.mjs +0 -150
  220. package/src/data/providers/hl-assets.mjs +0 -165
  221. package/src/data/providers/hl-info.mjs +0 -108
  222. package/src/data/providers/hl-markets.mjs +0 -210
  223. package/src/data/providers/hl-outcome.mjs +0 -61
  224. package/src/data/providers/hl-perps.mjs +0 -419
  225. package/src/data/providers/hl-staking.mjs +0 -353
  226. package/src/data/providers/hl-ws.mjs +0 -119
  227. package/src/data/providers/hyperevm-dex.mjs +0 -49
  228. package/src/data/providers/jito-mev.mjs +0 -117
  229. package/src/data/providers/jupiter-venues.mjs +0 -119
  230. package/src/data/providers/jupiter.mjs +0 -315
  231. package/src/data/providers/kamino-strategies.mjs +0 -143
  232. package/src/data/providers/l2beat-tvl.mjs +0 -42
  233. package/src/data/providers/lifi.mjs +0 -166
  234. package/src/data/providers/liquid-esplora.mjs +0 -152
  235. package/src/data/providers/magiceden-ordinals.mjs +0 -141
  236. package/src/data/providers/magiceden-sol.mjs +0 -406
  237. package/src/data/providers/mempool-lightning.mjs +0 -144
  238. package/src/data/providers/mempool-mining.mjs +0 -142
  239. package/src/data/providers/meteora-dlmm.mjs +0 -168
  240. package/src/data/providers/morpho.mjs +0 -177
  241. package/src/data/providers/nft-gallery.mjs +0 -163
  242. package/src/data/providers/nft-portfolio.mjs +0 -494
  243. package/src/data/providers/odos.mjs +0 -156
  244. package/src/data/providers/ondo.mjs +0 -31
  245. package/src/data/providers/oneinch.mjs +0 -174
  246. package/src/data/providers/opensea-multichain.mjs +0 -136
  247. package/src/data/providers/opensea-nft.mjs +0 -371
  248. package/src/data/providers/orca.mjs +0 -29
  249. package/src/data/providers/ordinals-runes.mjs +0 -180
  250. package/src/data/providers/pancakeswap.mjs +0 -28
  251. package/src/data/providers/paraswap.mjs +0 -125
  252. package/src/data/providers/pendle.mjs +0 -188
  253. package/src/data/providers/poly-clob.mjs +0 -283
  254. package/src/data/providers/poly-public.mjs +0 -96
  255. package/src/data/providers/poly-ws.mjs +0 -103
  256. package/src/data/providers/polygon-staking.mjs +0 -227
  257. package/src/data/providers/portfolio-history.mjs +0 -394
  258. package/src/data/providers/portfolio.mjs +0 -600
  259. package/src/data/providers/pyth-price-feeds.mjs +0 -172
  260. package/src/data/providers/raydium.mjs +0 -35
  261. package/src/data/providers/relayscan-mev.mjs +0 -72
  262. package/src/data/providers/rfq.mjs +0 -15
  263. package/src/data/providers/rh-agent.mjs +0 -59
  264. package/src/data/providers/sanctum-lst.mjs +0 -180
  265. package/src/data/providers/satflow.mjs +0 -341
  266. package/src/data/providers/signed-material-guard.mjs +0 -108
  267. package/src/data/providers/solana-rpc.mjs +0 -197
  268. package/src/data/providers/solend-lending.mjs +0 -166
  269. package/src/data/providers/spark-lend.mjs +0 -42
  270. package/src/data/providers/squid-router.mjs +0 -29
  271. package/src/data/providers/stargate.mjs +0 -29
  272. package/src/data/providers/sushiswap.mjs +0 -30
  273. package/src/data/providers/symbiotic-restaking.mjs +0 -41
  274. package/src/data/providers/thorchain.mjs +0 -36
  275. package/src/data/providers/traderjoe.mjs +0 -28
  276. package/src/data/providers/twap.mjs +0 -152
  277. package/src/data/providers/uniswap-v3.mjs +0 -457
  278. package/src/data/providers/uniswap-v4.mjs +0 -414
  279. package/src/data/providers/vertex.mjs +0 -41
  280. package/src/data/providers/wallet-watch.mjs +0 -264
  281. package/src/data/providers/wormhole.mjs +0 -28
  282. package/src/data/providers/yearn.mjs +0 -31
  283. package/src/data/providers/zerox.mjs +0 -167
  284. package/src/data/public-api-scan.mjs +0 -61
  285. package/src/data/quote-placeholder.mjs +0 -31
  286. package/src/desk/swap-prepare.mjs +0 -194
  287. package/src/equities/bridge.mjs +0 -388
  288. package/src/equities/fixtures/bridge_routes.json +0 -159
  289. package/src/equities/fixtures/dst_transitions.json +0 -29
  290. package/src/equities/fixtures/equity_dex_pools.json +0 -154
  291. package/src/equities/fixtures/hip3_l2books.json +0 -2711
  292. package/src/equities/fixtures/nyse_holidays.json +0 -1
  293. package/src/equities/fixtures/oracles.json +0 -100
  294. package/src/equities/fixtures/rh_pool_state.json +0 -244
  295. package/src/equities/fixtures/solana_xstocks.json +0 -704
  296. package/src/equities/fixtures/ton_xstocks.json +0 -35
  297. package/src/equities/fixtures/universe.json +0 -411
  298. package/src/equities/fixtures/venues.json +0 -3542
  299. package/src/equities/fixtures.mjs +0 -405
  300. package/src/equities/funding.mjs +0 -142
  301. package/src/equities/index.mjs +0 -166
  302. package/src/equities/liveness.mjs +0 -148
  303. package/src/equities/marketHours.mjs +0 -249
  304. package/src/equities/normalize.mjs +0 -295
  305. package/src/equities/num.mjs +0 -146
  306. package/src/equities/prepare.mjs +0 -95
  307. package/src/equities/rank.mjs +0 -260
  308. package/src/equities/sourceNum.mjs +0 -69
  309. package/src/equities/types.mjs +0 -220
  310. package/src/equities/venues/arcus-perp.mjs +0 -84
  311. package/src/equities/venues/arcus-spot.mjs +0 -105
  312. package/src/equities/venues/hyperliquid-hip3.mjs +0 -224
  313. package/src/equities/venues/rh-uniswap.mjs +0 -216
  314. package/src/equities/venues/solana-xstocks.mjs +0 -139
  315. package/src/equities/venues/ton-stonfi.mjs +0 -139
  316. package/src/exact-integer.mjs +0 -72
  317. package/src/exec-policy.mjs +0 -419
  318. package/src/flags.mjs +0 -15
  319. package/src/fresh-window.mjs +0 -76
  320. package/src/gmx-attestation.mjs +0 -176
  321. package/src/index.mjs +0 -107
  322. package/src/licensing/locals-only.mjs +0 -25
  323. package/src/nft-gas-war-guard.mjs +0 -139
  324. package/src/onboarding/agent-keys.mjs +0 -161
  325. package/src/onboarding/harness-configs.mjs +0 -102
  326. package/src/onboarding/index.mjs +0 -18
  327. package/src/onboarding/tiers.mjs +0 -139
  328. package/src/oracle-env.mjs +0 -55
  329. package/src/package-manifest.mjs +0 -42
  330. package/src/plugins/agent-plugin-loader.mjs +0 -225
  331. package/src/portfolio-risk.mjs +0 -170
  332. package/src/prepare-envelope.mjs +0 -204
  333. package/src/profile-upgrade.mjs +0 -277
  334. package/src/protocol-execution.mjs +0 -84
  335. package/src/protocol-templates/gate.mjs +0 -179
  336. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  337. package/src/public-api/agent-grants.mjs +0 -57
  338. package/src/public-api/buzz-integration.mjs +0 -267
  339. package/src/public-api/connect-agent.mjs +0 -424
  340. package/src/public-api/grants.mjs +0 -142
  341. package/src/public-api/http.mjs +0 -707
  342. package/src/public-api/metering.mjs +0 -111
  343. package/src/public-control/aa-adapter.mjs +0 -402
  344. package/src/public-control/build-registry.mjs +0 -227
  345. package/src/public-control/bundler-client.mjs +0 -357
  346. package/src/public-control/grant-indexer.mjs +0 -296
  347. package/src/public-control/policy-render.mjs +0 -69
  348. package/src/public-control/policy-schema.mjs +0 -322
  349. package/src/public-control/runtime-config.mjs +0 -275
  350. package/src/public-control/session-key-model.mjs +0 -379
  351. package/src/public-control/session-orchestrator.mjs +0 -418
  352. package/src/rfq/intent.mjs +0 -180
  353. package/src/rfq/sources.mjs +0 -181
  354. package/src/route-attestation.mjs +0 -132
  355. package/src/router/best-execution.mjs +0 -326
  356. package/src/router/index.mjs +0 -250
  357. package/src/router/integrator-fee.mjs +0 -135
  358. package/src/router/prepare-bridge.mjs +0 -293
  359. package/src/router/prepare-route.mjs +0 -398
  360. package/src/router/proposal.mjs +0 -311
  361. package/src/router/risk-classifier.mjs +0 -119
  362. package/src/router/route-sources.mjs +0 -364
  363. package/src/scanner/chains.config.mjs +0 -543
  364. package/src/scanner/contract.mjs +0 -270
  365. package/src/scanner/evm-scanner.mjs +0 -394
  366. package/src/scanner/index.mjs +0 -9
  367. package/src/scanner/v2-venue.mjs +0 -351
  368. package/src/scanner/v3-venue.mjs +0 -308
  369. package/src/scopes.mjs +0 -44
  370. package/src/sell-simulation.mjs +0 -167
  371. package/src/signals/engine.mjs +0 -146
  372. package/src/signals/index.mjs +0 -1
  373. package/src/token-transfer-guard.mjs +0 -188
  374. package/src/tui/app.mjs +0 -438
  375. package/src/tui/backend.mjs +0 -215
  376. package/src/tui/format.mjs +0 -272
  377. package/src/tui/gateway-client.mjs +0 -177
  378. package/src/tui/input.mjs +0 -501
  379. package/src/tui/memory.mjs +0 -105
  380. package/src/tui/meta-learn.mjs +0 -85
  381. package/src/tui/renderer.mjs +0 -443
  382. package/src/tui/scheduler.mjs +0 -205
  383. package/src/tui/skills-loader.mjs +0 -140
  384. package/src/tui/standalone-client.mjs +0 -752
  385. package/src/tui/theme.mjs +0 -81
  386. package/src/vault-attestation.mjs +0 -146
  387. package/src/venues.mjs +0 -206
  388. package/src/watch-preferences.mjs +0 -85
  389. /package/{profiles → dist/assets/profiles}/_template/SOUL.md +0 -0
  390. /package/{profiles → dist/assets/profiles}/_template/profile.json +0 -0
  391. /package/{profiles → dist/assets/profiles}/bitcoin-agent/SOUL.md +0 -0
  392. /package/{profiles → dist/assets/profiles}/bitcoin-agent/profile.json +0 -0
  393. /package/{profiles → dist/assets/profiles}/hyperliquid-agent/SOUL.md +0 -0
  394. /package/{profiles → dist/assets/profiles}/hyperliquid-agent/profile.json +0 -0
  395. /package/{profiles → dist/assets/profiles}/oracle/SOUL.md +0 -0
  396. /package/{profiles → dist/assets/profiles}/oracle/profile.json +0 -0
  397. /package/{profiles → dist/assets/profiles}/polymarket-agent/SOUL.md +0 -0
  398. /package/{profiles → dist/assets/profiles}/polymarket-agent/profile.json +0 -0
  399. /package/{profiles → dist/assets/profiles}/profile.schema.json +0 -0
  400. /package/{profiles → dist/assets/profiles}/protocol-builder/SOUL.md +0 -0
  401. /package/{profiles → dist/assets/profiles}/protocol-builder/profile.json +0 -0
  402. /package/{profiles → dist/assets/profiles}/robinhood-agent/SOUL.md +0 -0
  403. /package/{profiles → dist/assets/profiles}/robinhood-agent/profile.json +0 -0
  404. /package/{profiles → dist/assets/profiles}/solana-agent/SOUL.md +0 -0
  405. /package/{profiles → dist/assets/profiles}/solana-agent/profile.json +0 -0
  406. /package/{profiles → dist/assets/profiles}/stable-agent/SOUL.md +0 -0
  407. /package/{profiles → dist/assets/profiles}/stable-agent/profile.json +0 -0
  408. /package/{skills → dist/assets/skills}/balance/SKILL.md +0 -0
  409. /package/{skills → dist/assets/skills}/bitcoin-l1.md +0 -0
  410. /package/{skills → dist/assets/skills}/chain-defi-ecosystem-profiling.md +0 -0
  411. /package/{skills → dist/assets/skills}/evm-contract-research.md +0 -0
  412. /package/{skills → dist/assets/skills}/hyperliquid.md +0 -0
  413. /package/{skills → dist/assets/skills}/multichain-exec-desk.md +0 -0
  414. /package/{skills → dist/assets/skills}/oracle-action-semantics/SKILL.md +0 -0
  415. /package/{skills → dist/assets/skills}/oracle-best-execution/SKILL.md +0 -0
  416. /package/{skills → dist/assets/skills}/oracle-best-execution.md +0 -0
  417. /package/{skills → dist/assets/skills}/oracle-bitcoin/SKILL.md +0 -0
  418. /package/{skills → dist/assets/skills}/oracle-chain-graphs-telegram-cards/SKILL.md +0 -0
  419. /package/{skills → dist/assets/skills}/oracle-chat/SKILL.md +0 -0
  420. /package/{skills → dist/assets/skills}/oracle-chat/chain.SKILL.md +0 -0
  421. /package/{skills → dist/assets/skills}/oracle-chat/setup.SKILL.md +0 -0
  422. /package/{skills → dist/assets/skills}/oracle-circuit-breaker/SKILL.md +0 -0
  423. /package/{skills → dist/assets/skills}/oracle-contract-research/SKILL.md +0 -0
  424. /package/{skills → dist/assets/skills}/oracle-desk/SKILL.md +0 -0
  425. /package/{skills → dist/assets/skills}/oracle-desk.md +0 -0
  426. /package/{skills → dist/assets/skills}/oracle-dex-launch/SKILL.md +0 -0
  427. /package/{skills → dist/assets/skills}/oracle-equities/SKILL.md +0 -0
  428. /package/{skills → dist/assets/skills}/oracle-grants/SKILL.md +0 -0
  429. /package/{skills → dist/assets/skills}/oracle-hypercore-staking/SKILL.md +0 -0
  430. /package/{skills → dist/assets/skills}/oracle-hyperliquid/SKILL.md +0 -0
  431. /package/{skills → dist/assets/skills}/oracle-meme-token-sniper/SKILL.md +0 -0
  432. /package/{skills → dist/assets/skills}/oracle-multichain-nft-launch/SKILL.md +0 -0
  433. /package/{skills → dist/assets/skills}/oracle-multichain-token-launch/SKILL.md +0 -0
  434. /package/{skills → dist/assets/skills}/oracle-nft-gacha-launch/SKILL.md +0 -0
  435. /package/{skills → dist/assets/skills}/oracle-nft-mint-gas-war/SKILL.md +0 -0
  436. /package/{skills → dist/assets/skills}/oracle-polymarket/SKILL.md +0 -0
  437. /package/{skills → dist/assets/skills}/oracle-protocol-builder/SKILL.md +0 -0
  438. /package/{skills → dist/assets/skills}/oracle-protocol-security/SKILL.md +0 -0
  439. /package/{skills → dist/assets/skills}/oracle-public-product/SKILL.md +0 -0
  440. /package/{skills → dist/assets/skills}/oracle-receipts/SKILL.md +0 -0
  441. /package/{skills → dist/assets/skills}/oracle-receipts.md +0 -0
  442. /package/{skills → dist/assets/skills}/oracle-rfq-tokenized-assets/SKILL.md +0 -0
  443. /package/{skills → dist/assets/skills}/oracle-smart-wallet-scanner/SKILL.md +0 -0
  444. /package/{skills → dist/assets/skills}/oracle-solana/SKILL.md +0 -0
  445. /package/{skills → dist/assets/skills}/oracle-solana-nft/SKILL.md +0 -0
  446. /package/{skills → dist/assets/skills}/oracle-token-research/SKILL.md +0 -0
  447. /package/{skills → dist/assets/skills}/solana.md +0 -0
@@ -1,424 +0,0 @@
1
- // Oracle Public API — connect-agent contract (Slice D).
2
- //
3
- // BFF-safe, self-custodial contract that turns a user's "connect my agent"
4
- // request into an UNSIGNED grant payload the USER signs with their own wallet.
5
- //
6
- // Hard boundaries for this file:
7
- // - NEVER signs anything. There is no signer, no key material, no signature
8
- // field ever populated here. The output hands back the exact bytes the
9
- // user must sign themselves; signing happens client-side in the user's
10
- // own wallet, never on a server.
11
- // - Imports ONLY from the assigned public peers
12
- // (src/public-control/policy-schema.mjs, session-key-model.mjs).
13
- // Never from the private executor stack (get-signer, keystore,
14
- // exec-policy, local-signer/*, adapters/*).
15
- // - Oracle Control is deterministic authorization: same input => same
16
- // canonical bytes => same grant id. No advisory logic here (that is
17
- // Oracle Router's job and Router output never gates anything here).
18
- // - Fail-closed no-secret invariant: every object returned from this module
19
- // is recursively scanned and the call THROWS if anything shaped like a
20
- // private key, session secret, bearer token, keystore path, or signer URL
21
- // is present. See assertNoSecretMaterial().
22
-
23
- import {
24
- GRANT_VERSION,
25
- GrantValidationError,
26
- normalizeGrant,
27
- canonicalizeGrant,
28
- grantId,
29
- isReadonlyAction,
30
- } from "../public-control/policy-schema.mjs";
31
-
32
- export const CONNECT_REQUEST_KIND = "oracle-connect-request";
33
- export const UNSIGNED_GRANT_KIND = "oracle-unsigned-grant";
34
-
35
- /** Identifier for how the signable bytes are derived: utf-8 encoding of the
36
- * canonical grant JSON produced by policy-schema's canonicalizeGrant(). */
37
- export const SIGNING_SCHEME = "oracle-grant-canonical-json-utf8-v1";
38
-
39
- // ---------------------------------------------------------------------------
40
- // No-secret invariant (fail closed)
41
- // ---------------------------------------------------------------------------
42
-
43
- export class SecretLeakError extends Error {
44
- constructor(path, rule) {
45
- super(`secret material must never appear in a public API object (at ${path}, rule: ${rule})`);
46
- this.name = "SecretLeakError";
47
- this.path = path;
48
- this.rule = rule;
49
- }
50
- }
51
-
52
- /** Key names that must never appear on any object we return. */
53
- const FORBIDDEN_KEY_RE =
54
- /(private[_-]?key|secret|bearer|keystore|mnemonic|seed[_-]?phrase|passphrase|password|api[_-]?key|access[_-]?token|auth[_-]?token|session[_-]?token|signer[_-]?url|signature)/i;
55
-
56
- /** Short wallet-export aliases need exact normalized matching. Substring
57
- * matching `wif`, for example, would incorrectly reject an unrelated key such
58
- * as `swift`. Removing common separators catches snake/kebab/spaced variants
59
- * without widening those short aliases into arbitrary words. */
60
- const FORBIDDEN_KEY_ALIASES = Object.freeze(["privkey", "wif", "xprv", "seed"]);
61
-
62
- function isForbiddenKeyName(key) {
63
- const text = String(key);
64
- const normalized = text.toLowerCase().replace(/[\s._-]+/g, "");
65
- return FORBIDDEN_KEY_RE.test(text) || FORBIDDEN_KEY_ALIASES.includes(normalized);
66
- }
67
-
68
- /** String-value shapes that must never appear in any object we return. */
69
- const FORBIDDEN_VALUE_RULES = Object.freeze([
70
- // 32-byte hex — the shape of a raw EVM private key / session secret. Public
71
- // grant material never legitimately carries a 0x + 64-hex value (addresses
72
- // are 40 hex; the grant id is bare sha256 hex), so this fails closed.
73
- { rule: "raw-32-byte-hex-key", re: /^0x[0-9a-fA-F]{64}$/ },
74
- // Same 32 bytes WITHOUT the 0x prefix, as the entire string. A bare-hex
75
- // private key (the shape ethers and most wallet exports hand you) must not
76
- // pass just because it lacks the prefix.
77
- //
78
- // Deliberately anchored: an embedded/substring match would flag legitimate
79
- // prose that quotes a public sha256 identifier (the human-readable grant
80
- // render says "grant <id>"), and a scanner that cries wolf on normal output
81
- // gets disabled. Smuggling a key inside a longer string is still caught at
82
- // the serialized layer for any non-allowlisted field.
83
- { rule: "raw-32-byte-hex-bare", re: /^[0-9a-fA-F]{64}$/ },
84
- // BIP-32 private extended keys. Public xpub/tpub/ypub/zpub identifiers are
85
- // intentionally not matched; only their private-key counterparts fail.
86
- { rule: "extended-private-key", re: /\b(?:xprv|tprv|yprv|zprv)[1-9A-HJ-NP-Za-km-z]{107}\b/ },
87
- // Bitcoin WIF (mainnet 5/K/L, testnet uncompressed 9 or compressed c) —
88
- // base58, 51-52 chars.
89
- { rule: "bitcoin-wif", re: /\b[59KLc][1-9A-HJ-NP-Za-km-z]{50,51}\b/ },
90
- // BIP-39 mnemonic: 12/15/18/21/24 lowercase words. Detect a long run of
91
- // space-separated short alpha words rather than shipping the wordlist.
92
- { rule: "bip39-mnemonic", re: /\b(?:[a-z]{3,8}\s+){11,23}[a-z]{3,8}\b/ },
93
- { rule: "bearer-token", re: /bearer\s+[A-Za-z0-9._~+/=-]+/i },
94
- { rule: "pem-private-key", re: /-----BEGIN[A-Z ]*PRIVATE KEY-----/ },
95
- { rule: "keystore-path", re: /keystore/i },
96
- { rule: "signer-url", re: /https?:\/\/\S*sign/i },
97
- { rule: "authorization-header", re: /authorization\s*:/i },
98
- ]);
99
-
100
- /**
101
- * Field names whose values are legitimately 64-hex and are NOT secrets:
102
- * sha256 grant ids, tx hashes, block hashes, canonical digests. These are
103
- * public identifiers — the whole point of a grant id is that it is quotable.
104
- *
105
- * Deliberately EXCLUDED: `nonce` and `salt`. Those are caller-supplied on the
106
- * public path, so allowlisting them would let anyone launder key material
107
- * through the scan just by naming the field `nonce`. Oracle's own nonces are
108
- * short opaque strings, not 32-byte hex, so nothing legitimate is lost.
109
- */
110
- const HEX64_ALLOWED_KEYS = Object.freeze([
111
- "grantid",
112
- "id",
113
- "hash",
114
- "sha256",
115
- "sha256hex",
116
- "checksum",
117
- "txhash",
118
- "transactionhash",
119
- "blockhash",
120
- "digest",
121
- "userophash",
122
- "commithash",
123
- "prevhash",
124
- "intenthash",
125
- "canonicalhash",
126
- "payloadhash",
127
- "requestid",
128
- ]);
129
-
130
- /**
131
- * Strip values that are legitimately 64-hex public identifiers before running
132
- * the raw-key shape rules, so a sha256 grant id does not read as a private key.
133
- * Only exact-match 64-hex values on an allowlisted key are removed; a 64-hex
134
- * string sitting anywhere else still trips the rule.
135
- */
136
- function maskAllowedHex64(json) {
137
- return json.replace(
138
- /"([A-Za-z0-9_-]+)"\s*:\s*"(?:0x)?([0-9a-fA-F]{64})"/g,
139
- (match, key) =>
140
- HEX64_ALLOWED_KEYS.includes(String(key).toLowerCase().replace(/[_-]/g, ""))
141
- ? `"${key}":"<hex64>"`
142
- : match
143
- );
144
- }
145
- /**
146
- * Scan the SERIALIZED form of a payload.
147
- *
148
- * Scanning the object graph alone is not sufficient: `toJSON()`, getters,
149
- * symbol keys, non-enumerable properties and BigInt coercion all let a value
150
- * reach the wire in a shape the graph walk never visited. Verified: an object
151
- * `{ nested: { toJSON: () => "<private key>" } }` passes a graph-only scan and
152
- * then serializes the raw key into the response body.
153
- *
154
- * So the authoritative check runs against the exact bytes we are about to
155
- * write. Whatever JSON.stringify produces is what the client sees, and that is
156
- * what we scan. Returns the JSON string when clean; throws SecretLeakError
157
- * otherwise.
158
- */
159
- export function assertSerializedNoSecrets(value) {
160
- let json;
161
- try {
162
- json = JSON.stringify(value);
163
- } catch (e) {
164
- // A payload we cannot serialize (circular, BigInt, throwing toJSON) must
165
- // not be sent at all — fail closed rather than guess.
166
- throw new SecretLeakError("$", `unserializable-payload: ${String(e?.message || e)}`);
167
- }
168
- if (json === undefined) return "null";
169
-
170
- // Public 64-hex identifiers (grant ids, tx/block hashes, sha256 digests) are
171
- // masked first so they do not read as raw key material.
172
- const scanned = maskAllowedHex64(json);
173
-
174
- for (const { rule, re } of FORBIDDEN_VALUE_RULES) {
175
- if (re.test(scanned)) throw new SecretLeakError("$<serialized>", rule);
176
- }
177
-
178
- // Embedded key material. The per-string rules are anchored (so human-readable
179
- // prose quoting a public grant id does not trip them), but at the serialized
180
- // layer a 0x-prefixed 32-byte value has no legitimate reason to appear
181
- // anywhere in a public response — addresses are 40 hex, and every public
182
- // 64-hex identifier was masked above. This is what catches a key smuggled in
183
- // via toJSON(), a getter, or concatenated into a longer string.
184
- const embedded = /(?:^|[^0-9a-fA-Fx])0x[0-9a-fA-F]{64}(?![0-9a-fA-F])/;
185
- if (embedded.test(scanned)) {
186
- throw new SecretLeakError("$<serialized>", "raw-32-byte-hex-embedded");
187
- }
188
- // Parse the exact serialized bytes with a reviver so escaped or toJSON-made
189
- // key names receive the same normalization as real object properties. This
190
- // avoids maintaining a second, inevitably drifting key-name regex.
191
- JSON.parse(json, (key, item) => {
192
- if (key && isForbiddenKeyName(key)) {
193
- throw new SecretLeakError(`$<serialized>.${key}`, "forbidden-key-name");
194
- }
195
- return item;
196
- });
197
- return json;
198
- }
199
-
200
- /**
201
- * Recursively scan a value (objects, arrays, Maps, Sets, typed arrays) for
202
- * anything shaped like secret material. Throws SecretLeakError on the first
203
- * hit — fail closed. Returns the value unchanged when clean, so it can be
204
- * used inline: `return assertNoSecretMaterial(result)`.
205
- *
206
- * `keyHint` carries the property name a string was found under, so a 64-hex
207
- * value on a known public identifier (grantId, txHash, ...) is not mistaken
208
- * for raw key material. A 64-hex string under any other key still trips.
209
- */
210
- export function assertNoSecretMaterial(value, path = "$", seen = new Set(), keyHint = "") {
211
- if (value == null) return value;
212
- if (typeof value === "string") {
213
- const hex64Ok = HEX64_ALLOWED_KEYS.includes(
214
- String(keyHint).toLowerCase().replace(/[_-]/g, "")
215
- );
216
- for (const { rule, re } of FORBIDDEN_VALUE_RULES) {
217
- if (hex64Ok && rule.startsWith("raw-32-byte-hex")) continue;
218
- if (re.test(value)) throw new SecretLeakError(path, rule);
219
- }
220
- return value;
221
- }
222
- if (typeof value !== "object") return value;
223
- if (seen.has(value)) return value;
224
- seen.add(value);
225
-
226
- if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) return value;
227
- if (value instanceof Map) {
228
- for (const [k, v] of value.entries()) {
229
- if (typeof k === "string" && isForbiddenKeyName(k)) {
230
- throw new SecretLeakError(`${path}[${JSON.stringify(k)}]`, "forbidden-key-name");
231
- }
232
- assertNoSecretMaterial(k, `${path}[key]`, seen);
233
- assertNoSecretMaterial(v, `${path}[${String(k)}]`, seen);
234
- }
235
- return value;
236
- }
237
- if (value instanceof Set) {
238
- let i = 0;
239
- for (const v of value.values()) assertNoSecretMaterial(v, `${path}[${i++}]`, seen);
240
- return value;
241
- }
242
- if (Array.isArray(value)) {
243
- value.forEach((v, i) => assertNoSecretMaterial(v, `${path}[${i}]`, seen));
244
- return value;
245
- }
246
- for (const [k, v] of Object.entries(value)) {
247
- if (isForbiddenKeyName(k)) {
248
- throw new SecretLeakError(`${path}.${k}`, "forbidden-key-name");
249
- }
250
- assertNoSecretMaterial(v, `${path}.${k}`, seen, k);
251
- }
252
- return value;
253
- }
254
-
255
- // ---------------------------------------------------------------------------
256
- // Helpers
257
- // ---------------------------------------------------------------------------
258
-
259
- function deepFreeze(value) {
260
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
261
- Object.freeze(value);
262
- for (const v of Object.values(value)) deepFreeze(v);
263
- }
264
- return value;
265
- }
266
-
267
- function toUnixSeconds(v, label) {
268
- const n = typeof v === "string" ? Number(v.trim()) : Number(v);
269
- if (!Number.isSafeInteger(n) || n <= 0) {
270
- throw new GrantValidationError([{ field: label, message: "must be a positive unix-seconds integer" }]);
271
- }
272
- return n;
273
- }
274
-
275
- function requiredReferenceNow(opts) {
276
- if (opts?.now == null) {
277
- throw new GrantValidationError([
278
- { field: "opts.now", message: "explicit reference time is required for live grant construction" },
279
- ]);
280
- }
281
- return toUnixSeconds(opts.now, "opts.now");
282
- }
283
-
284
- /** Deterministic UTC ISO string from unix seconds. */
285
- function isoUtc(unixSeconds) {
286
- return new Date(unixSeconds * 1000).toISOString();
287
- }
288
-
289
- /** Deterministic, purely-presentational human render of a normalized grant.
290
- * Presentation only — it never adds, removes, or reinterprets authority and
291
- * only surfaces public grant material. */
292
- function renderUnsignedGrant(grant, id) {
293
- const readonlyOnly = grant.actions.every((a) => isReadonlyAction(a));
294
- return [
295
- "ORACLE — CONNECT AGENT (unsigned grant, you sign it, we never do)",
296
- "=================================================================",
297
- `Grant ID: ${id}`,
298
- `Version: ${GRANT_VERSION}`,
299
- `Chain: ${grant.chainId}`,
300
- `Agent: ${grant.agentAddress}`,
301
- `Your account: ${grant.accountAddress}`,
302
- `Actions: ${grant.actions.join(", ")}`,
303
- `Targets: ${grant.targets.length ? grant.targets.join(", ") : "(none — read/simulate only)"}`,
304
- `Max value: ${grant.maxValueWei} wei`,
305
- `Max gas: ${grant.maxGasWei} wei`,
306
- `Max slippage: ${grant.maxSlippageBps} bps`,
307
- `Expires: ${isoUtc(grant.expiresAt)} (unix ${grant.expiresAt})`,
308
- `Nonce: ${grant.nonce}`,
309
- `Revocation: ${grant.revocationKey}`,
310
- "-----------------------------------------------------------------",
311
- readonlyOnly
312
- ? "Scope: read/simulate only — this grant cannot move funds."
313
- : "Scope: includes state-changing actions bounded by the caps above.",
314
- "Self-custodial: this payload is UNSIGNED and contains public data only.",
315
- "Sign the bytes below with YOUR wallet; Oracle never holds your keys.",
316
- ].join("\n");
317
- }
318
-
319
- // ---------------------------------------------------------------------------
320
- // Public contract
321
- // ---------------------------------------------------------------------------
322
-
323
- /**
324
- * Turn raw user inputs into a validated connect request.
325
- *
326
- * Accepts the canonical grant fields (see policy-schema REQUIRED_FIELDS).
327
- * Every live construction requires explicit `opts.now` (unix seconds).
328
- * Convenience: instead of `expiresAt` the caller may pass `ttlSeconds`.
329
- * Determinism requires the library caller to supply `now`; the HTTP boundary
330
- * overwrites caller time with the server clock.
331
- *
332
- * Throws GrantValidationError on any invalid/unknown/missing field (the
333
- * schema fails closed on unknown fields, wildcard actions, empty targets for
334
- * state-changing scopes, etc). Never signs anything.
335
- *
336
- * @returns frozen { kind, version, grant } where grant is the normalized
337
- * canonical grant from policy-schema.
338
- */
339
- export function buildConnectRequest(input = {}, opts = {}) {
340
- if (input == null || typeof input !== "object" || Array.isArray(input)) {
341
- throw new GrantValidationError([{ field: "request", message: "request must be a plain object" }]);
342
- }
343
- const now = requiredReferenceNow(opts);
344
-
345
- const { ttlSeconds, ...rest } = input;
346
- const fields = { ...rest };
347
-
348
- if (ttlSeconds != null) {
349
- if (fields.expiresAt != null) {
350
- throw new GrantValidationError([
351
- { field: "ttlSeconds", message: "pass either ttlSeconds or expiresAt, not both" },
352
- ]);
353
- }
354
- const ttl = toUnixSeconds(ttlSeconds, "ttlSeconds");
355
- fields.expiresAt = now + ttl;
356
- }
357
-
358
- const grant = normalizeGrant(fields, {
359
- now,
360
- allowWildcardActions: opts.allowWildcardActions === true,
361
- });
362
-
363
- const request = deepFreeze({
364
- kind: CONNECT_REQUEST_KIND,
365
- version: GRANT_VERSION,
366
- grant,
367
- });
368
- return assertNoSecretMaterial(request);
369
- }
370
-
371
- /**
372
- * Assemble the UNSIGNED grant payload for a connect request (or raw grant
373
- * input). Returns everything a BFF/browser needs to show the user what they
374
- * are approving and exactly which bytes to sign — and nothing else:
375
- *
376
- * payload — { version, grantId, grant, canonical } canonical grant data
377
- * signing — { scheme, message, bytesHex, byteLength, sha256 } where
378
- * `message` is the exact canonical JSON string and `bytesHex`
379
- * is the 0x-hex of its utf-8 bytes: THE bytes the user signs.
380
- * render — deterministic human-readable review text
381
- * unsigned — always true; this module never signs and never will.
382
- *
383
- * Deterministic: identical grants (any key order / address casing / numeric
384
- * representation) produce byte-identical canonical/message/bytesHex/grantId.
385
- *
386
- * Fail-closed: requires explicit `opts.now`, throws GrantValidationError on bad
387
- * input, and throws SecretLeakError if the assembled object ever carried
388
- * secret-shaped material.
389
- */
390
- export function assembleUnsignedGrant(requestOrInput = {}, opts = {}) {
391
- const now = requiredReferenceNow(opts);
392
- const raw =
393
- requestOrInput && requestOrInput.kind === CONNECT_REQUEST_KIND
394
- ? requestOrInput.grant
395
- : requestOrInput;
396
-
397
- const grant = normalizeGrant(raw, {
398
- now,
399
- allowWildcardActions: opts.allowWildcardActions === true,
400
- });
401
- const canonical = canonicalizeGrant(grant);
402
- const id = grantId(grant);
403
- const bytes = Buffer.from(canonical, "utf8");
404
-
405
- const result = deepFreeze({
406
- kind: UNSIGNED_GRANT_KIND,
407
- unsigned: true,
408
- payload: deepFreeze({
409
- version: GRANT_VERSION,
410
- grantId: id,
411
- grant,
412
- canonical,
413
- }),
414
- signing: deepFreeze({
415
- scheme: SIGNING_SCHEME,
416
- message: canonical,
417
- bytesHex: `0x${bytes.toString("hex")}`,
418
- byteLength: bytes.length,
419
- sha256: id,
420
- }),
421
- render: renderUnsignedGrant(grant, id),
422
- });
423
- return assertNoSecretMaterial(result);
424
- }
@@ -1,142 +0,0 @@
1
- // Oracle Public API — grant reads (Slice D).
2
- //
3
- // Pure, deterministic read functions over an INJECTED grant store. No DB, no
4
- // chain, no clock fallback: callers pass an array/Map of grant records plus an
5
- // explicit `now` (unix seconds). Same inputs always produce the same output.
6
- //
7
- // Imports ONLY from the assigned public peers (policy-schema.mjs) and the
8
- // sibling connect-agent.mjs for the shared no-secret invariant. Never from the
9
- // private executor stack.
10
- //
11
- // Store shape (injected, caller-owned):
12
- // - an Array or Map whose entries are either
13
- // a) a raw grant object (policy-schema shape), or
14
- // b) a wrapper record { grant, revoked?, revokedAt? }.
15
- // - revocation may also be supplied out-of-band via opts.revoked: a Set /
16
- // array / Map-like of grant ids and/or revocation keys, or a function
17
- // (id, grant) => boolean.
18
- //
19
- // Fail-closed rules:
20
- // - records that do not validate against the public policy schema are
21
- // EXCLUDED from active listings (a grant that cannot validate cannot
22
- // authorize anything).
23
- // - `now` is required for listActiveGrants; without a reference time we
24
- // cannot prove liveness, so we refuse rather than guess.
25
- // - every returned object passes the no-secret invariant scan.
26
-
27
- import { validateGrant, grantId, isExpired } from "../public-control/policy-schema.mjs";
28
- import { assertNoSecretMaterial } from "./connect-agent.mjs";
29
-
30
- export const GRANT_STATUS = Object.freeze({
31
- ACTIVE: "active",
32
- EXPIRED: "expired",
33
- REVOKED: "revoked",
34
- INVALID: "invalid",
35
- });
36
-
37
- function toRecords(store) {
38
- if (store == null) return [];
39
- if (Array.isArray(store)) return store;
40
- if (store instanceof Map) return [...store.values()];
41
- if (typeof store[Symbol.iterator] === "function") return [...store];
42
- throw new TypeError("grant store must be an array, Map, or iterable of grant records");
43
- }
44
-
45
- function unwrap(record) {
46
- if (record && typeof record === "object" && !Array.isArray(record) && record.grant != null) {
47
- return {
48
- grant: record.grant,
49
- revoked: record.revoked === true || record.revokedAt != null,
50
- };
51
- }
52
- return { grant: record, revoked: false };
53
- }
54
-
55
- function toSafeNow(now) {
56
- const n = typeof now === "string" ? Number(now.trim()) : Number(now);
57
- if (!Number.isSafeInteger(n) || n < 0) {
58
- throw new TypeError("an explicit unix-seconds `now` is required (deterministic liveness, no wall-clock fallback)");
59
- }
60
- return n;
61
- }
62
-
63
- function isRevokedBy(revoked, id, grant) {
64
- if (revoked == null) return false;
65
- if (typeof revoked === "function") return revoked(id, grant) === true;
66
- const keys = [id, grant.revocationKey];
67
- if (revoked instanceof Set) return keys.some((k) => revoked.has(k));
68
- if (Array.isArray(revoked)) return keys.some((k) => revoked.includes(k));
69
- if (typeof revoked.has === "function") return keys.some((k) => revoked.has(k));
70
- return false;
71
- }
72
-
73
- /**
74
- * Classify a single store record. Returns { status, id, grant } where grant
75
- * is the normalized public grant (null when invalid). Pure + deterministic.
76
- */
77
- export function classifyGrant(record, { now, revoked } = {}) {
78
- const nowSec = toSafeNow(now);
79
- const { grant: raw, revoked: recordRevoked } = unwrap(record);
80
- const { ok, grant } = validateGrant(raw);
81
- if (!ok) return { status: GRANT_STATUS.INVALID, id: null, grant: null };
82
- const id = grantId(grant);
83
- // Revocation takes precedence over expiry (matches session-key-model
84
- // semantics: a revoked-then-expired grant still reports "revoked").
85
- if (recordRevoked || isRevokedBy(revoked, id, grant)) {
86
- return { status: GRANT_STATUS.REVOKED, id, grant };
87
- }
88
- if (isExpired(grant, nowSec)) return { status: GRANT_STATUS.EXPIRED, id, grant };
89
- return { status: GRANT_STATUS.ACTIVE, id, grant };
90
- }
91
-
92
- /**
93
- * List grants that are currently ACTIVE: valid under the public policy
94
- * schema, not expired at `now`, and not revoked (per record flag or the
95
- * injected `revoked` source). Invalid records are silently excluded
96
- * (fail closed — they cannot authorize anything).
97
- *
98
- * Optional filters: { agentAddress, accountAddress, chainId }.
99
- *
100
- * @returns frozen array of { id, grant } sorted by id (deterministic order).
101
- */
102
- export function listActiveGrants(store, { now, revoked, agentAddress, accountAddress, chainId } = {}) {
103
- const nowSec = toSafeNow(now);
104
- const wantAgent = agentAddress != null ? String(agentAddress).trim().toLowerCase() : null;
105
- const wantAccount = accountAddress != null ? String(accountAddress).trim().toLowerCase() : null;
106
- const wantChain = chainId != null ? Number(chainId) : null;
107
-
108
- const out = [];
109
- for (const record of toRecords(store)) {
110
- const { status, id, grant } = classifyGrant(record, { now: nowSec, revoked });
111
- if (status !== GRANT_STATUS.ACTIVE) continue;
112
- if (wantAgent != null && grant.agentAddress !== wantAgent) continue;
113
- if (wantAccount != null && grant.accountAddress !== wantAccount) continue;
114
- if (wantChain != null && grant.chainId !== wantChain) continue;
115
- out.push(Object.freeze({ id, grant }));
116
- }
117
- out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
118
- return assertNoSecretMaterial(Object.freeze(out));
119
- }
120
-
121
- /**
122
- * Look up a single grant by its public grant id. Returns
123
- * { id, status, grant } or null when no record in the store matches.
124
- * Unlike listActiveGrants this also surfaces expired/revoked grants (with
125
- * their status) so a UI can explain WHY a grant is not active — but invalid
126
- * records never match (they have no trustworthy id).
127
- */
128
- export function getGrant(store, id, { now, revoked } = {}) {
129
- const nowSec = toSafeNow(now);
130
- const wanted = String(id ?? "").trim().toLowerCase();
131
- if (!/^[0-9a-f]{64}$/.test(wanted)) return null;
132
- for (const record of toRecords(store)) {
133
- const res = classifyGrant(record, { now: nowSec, revoked });
134
- if (res.status === GRANT_STATUS.INVALID) continue;
135
- if (res.id === wanted) {
136
- return assertNoSecretMaterial(
137
- Object.freeze({ id: res.id, status: res.status, grant: res.grant })
138
- );
139
- }
140
- }
141
- return null;
142
- }