auramaxx 0.0.17 → 0.0.19

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 (296) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-build-manifest.json +70 -70
  3. package/.next/app-path-routes-manifest.json +2 -2
  4. package/.next/build-manifest.json +5 -5
  5. package/.next/prerender-manifest.json +30 -30
  6. package/.next/react-loadable-manifest.json +16 -16
  7. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  8. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  9. package/.next/server/app/_not-found.html +1 -1
  10. package/.next/server/app/_not-found.rsc +5 -5
  11. package/.next/server/app/api/[...doc]/page.js.nft.json +1 -1
  12. package/.next/server/app/api/[...doc]/page_client-reference-manifest.js +1 -1
  13. package/.next/server/app/api/agent-requests/route_client-reference-manifest.js +1 -1
  14. package/.next/server/app/api/apps/install/route.js.nft.json +1 -1
  15. package/.next/server/app/api/apps/install/route_client-reference-manifest.js +1 -1
  16. package/.next/server/app/api/apps/manifests/route_client-reference-manifest.js +1 -1
  17. package/.next/server/app/api/apps/static/[...path]/route_client-reference-manifest.js +1 -1
  18. package/.next/server/app/api/docs/plain/route.js.nft.json +1 -1
  19. package/.next/server/app/api/docs/plain/route_client-reference-manifest.js +1 -1
  20. package/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
  21. package/.next/server/app/api/import-from-openclaw/[channel]/route.js.nft.json +1 -1
  22. package/.next/server/app/api/import-from-openclaw/[channel]/route_client-reference-manifest.js +1 -1
  23. package/.next/server/app/api/import-from-openclaw/route.js.nft.json +1 -1
  24. package/.next/server/app/api/import-from-openclaw/route_client-reference-manifest.js +1 -1
  25. package/.next/server/app/api/import-from-openclaw/validate/[channel]/route.js.nft.json +1 -1
  26. package/.next/server/app/api/import-from-openclaw/validate/[channel]/route_client-reference-manifest.js +1 -1
  27. package/.next/server/app/api/page.js.nft.json +1 -1
  28. package/.next/server/app/api/page_client-reference-manifest.js +1 -1
  29. package/.next/server/app/api/restart/route_client-reference-manifest.js +1 -1
  30. package/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
  31. package/.next/server/app/api/version/route_client-reference-manifest.js +1 -1
  32. package/.next/server/app/api/workspace/[id]/apps/[wid]/route_client-reference-manifest.js +1 -1
  33. package/.next/server/app/api/workspace/[id]/apps/route_client-reference-manifest.js +1 -1
  34. package/.next/server/app/api/workspace/[id]/export/route_client-reference-manifest.js +1 -1
  35. package/.next/server/app/api/workspace/[id]/route_client-reference-manifest.js +1 -1
  36. package/.next/server/app/api/workspace/config/route_client-reference-manifest.js +1 -1
  37. package/.next/server/app/api/workspace/import/route_client-reference-manifest.js +1 -1
  38. package/.next/server/app/api/workspace/route_client-reference-manifest.js +1 -1
  39. package/.next/server/app/app-legacy-do-not-use/page.js +3 -3
  40. package/.next/server/app/app-legacy-do-not-use/page.js.nft.json +1 -1
  41. package/.next/server/app/app-legacy-do-not-use/page_client-reference-manifest.js +1 -1
  42. package/.next/server/app/app-legacy-do-not-use.html +1 -1
  43. package/.next/server/app/app-legacy-do-not-use.rsc +6 -6
  44. package/.next/server/app/approve/[actionId]/page.js.nft.json +1 -1
  45. package/.next/server/app/approve/[actionId]/page_client-reference-manifest.js +1 -1
  46. package/.next/server/app/docs/[...doc]/page.js.nft.json +1 -1
  47. package/.next/server/app/docs/[...doc]/page_client-reference-manifest.js +1 -1
  48. package/.next/server/app/docs/page.js.nft.json +1 -1
  49. package/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  50. package/.next/server/app/health/page.js.nft.json +1 -1
  51. package/.next/server/app/health/page_client-reference-manifest.js +1 -1
  52. package/.next/server/app/health.html +1 -1
  53. package/.next/server/app/health.rsc +5 -5
  54. package/.next/server/app/hello/page.js.nft.json +1 -1
  55. package/.next/server/app/hello/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/hello.html +1 -1
  57. package/.next/server/app/hello.rsc +5 -5
  58. package/.next/server/app/index.html +1 -1
  59. package/.next/server/app/index.rsc +6 -6
  60. package/.next/server/app/page.js +9 -3
  61. package/.next/server/app/page.js.nft.json +1 -1
  62. package/.next/server/app/page_client-reference-manifest.js +1 -1
  63. package/.next/server/app/privacy/page.js.nft.json +1 -1
  64. package/.next/server/app/privacy/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/privacy.html +1 -1
  66. package/.next/server/app/privacy.rsc +5 -5
  67. package/.next/server/app/share/[token]/page.js.nft.json +1 -1
  68. package/.next/server/app/share/[token]/page_client-reference-manifest.js +1 -1
  69. package/.next/server/app/terms/page.js.nft.json +1 -1
  70. package/.next/server/app/terms/page_client-reference-manifest.js +1 -1
  71. package/.next/server/app/terms.html +1 -1
  72. package/.next/server/app/terms.rsc +5 -5
  73. package/.next/server/app/yo/page.js +1 -1
  74. package/.next/server/app/yo/page.js.nft.json +1 -1
  75. package/.next/server/app/yo/page_client-reference-manifest.js +1 -1
  76. package/.next/server/app/yo.html +1 -1
  77. package/.next/server/app/yo.rsc +6 -6
  78. package/.next/server/app-paths-manifest.json +2 -2
  79. package/.next/server/chunks/1196.js +1 -1
  80. package/.next/server/chunks/{6415.js → 2123.js} +2 -2
  81. package/.next/server/chunks/2234.js +1 -1
  82. package/.next/server/chunks/4224.js +1 -0
  83. package/.next/server/chunks/4600.js +1 -1
  84. package/.next/server/chunks/5678.js +1 -1
  85. package/.next/server/chunks/5991.js +7 -0
  86. package/.next/server/chunks/6470.js +1 -1
  87. package/.next/server/chunks/7585.js +1 -1
  88. package/.next/server/chunks/7935.js +19 -11
  89. package/.next/server/chunks/8468.js +1 -1
  90. package/.next/server/chunks/{1350.js → 9323.js} +3 -3
  91. package/.next/server/chunks/9971.js +1 -1
  92. package/.next/server/functions-config-manifest.json +1 -1
  93. package/.next/server/middleware-build-manifest.js +1 -1
  94. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  95. package/.next/server/pages/404.html +1 -1
  96. package/.next/server/pages/500.html +1 -1
  97. package/.next/server/server-reference-manifest.json +1 -1
  98. package/.next/static/chunks/{1168.aaac1edbb597fe5a.js → 1168.bb1c93965872e980.js} +1 -1
  99. package/.next/static/chunks/2891-bf010357841c9ce9.js +1 -0
  100. package/.next/static/chunks/{2927.7e00cc878d9a3f52.js → 2927.3976471e61df966e.js} +1 -1
  101. package/.next/static/chunks/{3573-1b41d7b8a000d015.js → 3573-667bc4c8f56afcff.js} +1 -1
  102. package/.next/static/chunks/{3a91511d-ba215c0b5dc21ba9.js → 3a91511d-da2c74cad6c6fc33.js} +2 -2
  103. package/.next/static/chunks/4114-a375178fd94c4d8a.js +1 -0
  104. package/.next/static/chunks/{4256.48407d9abad5ea33.js → 4256.aa831e4d8c3f65bc.js} +1 -1
  105. package/.next/static/chunks/{4919-7e7cdd5efc9f2110.js → 4919-0e698cd95504e355.js} +1 -1
  106. package/.next/static/chunks/{5336-233ec7ab3807267c.js → 5336-b775f449d7433604.js} +1 -1
  107. package/.next/static/chunks/{7338-3ce17a93614f1d77.js → 5362-2e8fcdd0bc6273ca.js} +4 -4
  108. package/.next/static/chunks/67-cb9bbb430499e803.js +1 -0
  109. package/.next/static/chunks/{8273-8e92d34180669ca9.js → 8273-3b9d882c5dd6a9a8.js} +1 -1
  110. package/.next/static/chunks/8291-8f6fb6554e692552.js +1 -0
  111. package/.next/static/chunks/8370-6537b6b27df58b23.js +1 -0
  112. package/.next/static/chunks/app/app-legacy-do-not-use/page-efa348da049c5873.js +1 -0
  113. package/.next/static/chunks/app/{error-63cbe72522239cff.js → error-04a18fd49a89ee17.js} +1 -1
  114. package/.next/static/chunks/app/layout-7093dda0d106f34d.js +1 -0
  115. package/.next/static/chunks/app/page-0ec7cf48550f71e6.js +1 -0
  116. package/.next/static/chunks/app/yo/{page-cf5d6540ea31c31c.js → page-48930746b135037e.js} +1 -1
  117. package/.next/static/chunks/{webpack-79ad58260e9b10b4.js → webpack-15ec0114c9d658c2.js} +1 -1
  118. package/.next/static/css/35991998d1b5eff0.css +3 -0
  119. package/.next/trace +28 -28
  120. package/README.md +2 -2
  121. package/bin/auramaxx.js +87 -3
  122. package/package.json +8 -4
  123. package/prisma/migrations/20260301225214_social_tables/migration.sql +81 -0
  124. package/prisma/migrations/20260302120000_add_notification_hash/migration.sql +8 -0
  125. package/prisma/migrations/20260302160000_add_public_key_hex/migration.sql +5 -0
  126. package/prisma/migrations/20260302170000_add_inbound_author_public_key/migration.sql +5 -0
  127. package/prisma/schema.prisma +272 -177
  128. package/shared/credential-field-schema.ts +10 -0
  129. package/skills/auramaxx/SKILL.md +33 -4
  130. package/skills/auramaxx/docs/AGENT_SETUP.md +7 -2
  131. package/src/app/UnlockPageClient.tsx +448 -43
  132. package/src/app/app-legacy-do-not-use/page.tsx +5 -3
  133. package/src/app/globals.css +1 -1
  134. package/src/components/AgentPicker.tsx +278 -0
  135. package/src/components/CreateAgentModal.tsx +192 -0
  136. package/src/components/NotificationDrawer.tsx +15 -13
  137. package/src/components/agent/AgentSidebar.tsx +2 -19
  138. package/src/components/agent/CredentialAgent.tsx +70 -37
  139. package/src/components/agent/CredentialForm.tsx +32 -7
  140. package/src/components/agent/CredentialList.tsx +149 -72
  141. package/src/components/agents/AgentsView.tsx +1035 -0
  142. package/src/components/design-system/TextAreaInput.tsx +78 -0
  143. package/src/components/design-system/index.ts +1 -0
  144. package/src/components/hub/HubView.tsx +58 -0
  145. package/src/components/layout/LeftRail.tsx +333 -40
  146. package/src/components/layout/ViewShell.tsx +125 -0
  147. package/src/components/layout/index.ts +1 -0
  148. package/src/components/social/PrimaryHubRegistrationGate.tsx +260 -0
  149. package/src/components/social/SocialView.tsx +904 -0
  150. package/src/hooks/useSocialNotifications.ts +123 -0
  151. package/src/lib/events.ts +10 -1
  152. package/src/lib/social-client.ts +319 -0
  153. package/src/lib/view-registry.ts +22 -4
  154. package/src/server/cli/commands/agent.ts +33 -7
  155. package/src/server/cli/commands/create.ts +209 -0
  156. package/src/server/cli/commands/onboard.ts +39 -0
  157. package/src/server/cli/commands/play.ts +68 -0
  158. package/src/server/cli/commands/register-agent.ts +181 -0
  159. package/src/server/cli/commands/social.ts +648 -0
  160. package/src/server/cli/commands/start.ts +4 -3
  161. package/src/server/cron/index.ts +5 -9
  162. package/src/server/cron/jobs/social-inbound.ts +596 -0
  163. package/src/server/cron/jobs/social-outbound.ts +70 -0
  164. package/src/server/index.ts +14 -0
  165. package/src/server/lib/agent-profiles.ts +10 -1
  166. package/src/server/lib/cold.ts +0 -45
  167. package/src/server/lib/credential-import.ts +53 -47
  168. package/src/server/lib/defaults.ts +11 -0
  169. package/src/server/lib/feature-flags.ts +3 -0
  170. package/src/server/lib/hub-auth.ts +159 -0
  171. package/src/server/lib/migrate-agent-profiles.ts +96 -0
  172. package/src/server/lib/notifications.ts +12 -1
  173. package/src/server/lib/permissions.ts +10 -0
  174. package/src/server/lib/project-scope.ts +33 -5
  175. package/src/server/lib/social/create.ts +176 -0
  176. package/src/server/lib/social/global-aura-id.ts +115 -0
  177. package/src/server/lib/social/hub-rpc-client.ts +99 -0
  178. package/src/server/lib/social/hub-session.ts +6 -0
  179. package/src/server/lib/social/public-key.ts +32 -0
  180. package/src/server/lib/social/register.ts +162 -0
  181. package/src/server/lib/social/sign.ts +95 -0
  182. package/src/server/lib/social/sync.ts +301 -0
  183. package/src/server/mcp/server.ts +142 -18
  184. package/src/server/mcp/tools.ts +552 -0
  185. package/src/server/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  186. package/src/server/routes/agent-hub.ts +276 -0
  187. package/src/server/routes/agent-profiles.ts +145 -19
  188. package/src/server/routes/credentials.ts +49 -15
  189. package/src/server/routes/heartbeat.ts +3 -7
  190. package/src/server/routes/passkey.ts +7 -1
  191. package/src/server/routes/social.ts +869 -0
  192. package/src/server/routes/unlock.ts +17 -1
  193. package/src/server/routes/verified-credentials.ts +312 -0
  194. package/src/server/test-data/template.db +0 -0
  195. package/src/server/test-data/worker-1/agent-primary.json +12 -0
  196. package/src/server/test-data/worker-1/auramaxx.db +0 -0
  197. package/src/server/test-data/worker-1/backups/auramaxx.db.20260305_011404.bak +0 -0
  198. package/src/server/test-data/worker-1/backups/credentials.20260305_011404.cred-00ntf5h3.json +24 -0
  199. package/src/server/test-data/worker-1/backups/credentials.20260305_011404.cred-dh8fa9k3.json +24 -0
  200. package/src/server/test-data/worker-1/backups/credentials.20260305_011404.cred-prfhlyow.json +25 -0
  201. package/src/server/test-data/worker-1/backups/credentials.20260305_011404.cred-w26jd6zi.json +22 -0
  202. package/src/server/test-data/worker-1/config.json +33 -0
  203. package/src/server/test-data/worker-1/test.db +0 -0
  204. package/src/server/test-data/worker-10/agent-primary.json +12 -0
  205. package/src/server/test-data/worker-10/config.json +33 -0
  206. package/src/server/test-data/worker-10/test.db +0 -0
  207. package/src/server/test-data/worker-11/agent-primary.json +12 -0
  208. package/src/server/test-data/worker-11/config.json +33 -0
  209. package/src/server/test-data/worker-11/test.db +0 -0
  210. package/src/server/test-data/worker-12/agent-primary.json +12 -0
  211. package/src/server/test-data/worker-12/config.json +33 -0
  212. package/src/server/test-data/worker-12/credentials/cred-hboagned.json +25 -0
  213. package/src/server/test-data/worker-12/credentials/cred-nt14xd9t.json +24 -0
  214. package/src/server/test-data/worker-12/credentials/cred-qn59xefc.json +24 -0
  215. package/src/server/test-data/worker-12/test.db +0 -0
  216. package/src/server/test-data/worker-13/agent-primary.json +12 -0
  217. package/src/server/test-data/worker-13/approval-context.json +56 -0
  218. package/src/server/test-data/worker-13/approval-context.key +1 -0
  219. package/src/server/test-data/worker-13/config.json +33 -0
  220. package/src/server/test-data/worker-13/credentials-recently-deleted/cred-jn9yqy2m.json +20 -0
  221. package/src/server/test-data/worker-13/test.db +0 -0
  222. package/src/server/test-data/worker-14/agent-primary.json +12 -0
  223. package/src/server/test-data/worker-14/config.json +33 -0
  224. package/src/server/test-data/worker-14/test.db +0 -0
  225. package/src/server/test-data/worker-15/agent-primary.json +12 -0
  226. package/src/server/test-data/worker-15/config.json +33 -0
  227. package/src/server/test-data/worker-15/test.db +0 -0
  228. package/src/server/test-data/worker-15/update-check-4b305e76.json +5 -0
  229. package/src/server/test-data/worker-2/agent-primary.json +12 -0
  230. package/src/server/test-data/worker-2/config.json +33 -0
  231. package/src/server/test-data/worker-2/test.db +0 -0
  232. package/src/server/test-data/worker-3/agent-primary.json +12 -0
  233. package/src/server/test-data/worker-3/config.json +33 -0
  234. package/src/server/test-data/worker-3/test.db +0 -0
  235. package/src/server/test-data/worker-4/agent-primary.json +12 -0
  236. package/src/server/test-data/worker-4/config.json +33 -0
  237. package/src/server/test-data/worker-4/credentials/cred-bm6p74u5.json +24 -0
  238. package/src/server/test-data/worker-4/credentials/cred-r8eqb07i.json +25 -0
  239. package/src/server/test-data/worker-4/credentials/cred-ziv49y9h.json +24 -0
  240. package/src/server/test-data/worker-4/test.db +0 -0
  241. package/src/server/test-data/worker-5/agent-primary.json +12 -0
  242. package/src/server/test-data/worker-5/config.json +33 -0
  243. package/src/server/test-data/worker-5/credentials/cred-15gyfeht.json +25 -0
  244. package/src/server/test-data/worker-5/credentials/cred-lp0ocnfc.json +24 -0
  245. package/src/server/test-data/worker-5/credentials/cred-zfbwfxw0.json +24 -0
  246. package/src/server/test-data/worker-5/test.db +0 -0
  247. package/src/server/test-data/worker-6/agent-primary.json +12 -0
  248. package/src/server/test-data/worker-6/config.json +33 -0
  249. package/src/server/test-data/worker-6/credentials/cred-dx8li3ue.json +24 -0
  250. package/src/server/test-data/worker-6/credentials/cred-myeskqky.json +24 -0
  251. package/src/server/test-data/worker-6/credentials/cred-tam01qdt.json +25 -0
  252. package/src/server/test-data/worker-6/credentials/cred-wdh6rslw.json +22 -0
  253. package/src/server/test-data/worker-6/credentials-archive/cred-4wg53v1y.json +25 -0
  254. package/src/server/test-data/worker-6/test.db +0 -0
  255. package/src/server/test-data/worker-7/agent-primary.json +12 -0
  256. package/src/server/test-data/worker-7/config.json +33 -0
  257. package/src/server/test-data/worker-7/credentials/cred-ji7ec57d.json +25 -0
  258. package/src/server/test-data/worker-7/credentials/cred-mmgj0ypo.json +24 -0
  259. package/src/server/test-data/worker-7/credentials/cred-nb0ic93x.json +24 -0
  260. package/src/server/test-data/worker-7/test.db +0 -0
  261. package/src/server/test-data/worker-8/agent-primary.json +12 -0
  262. package/src/server/test-data/worker-8/config.json +33 -0
  263. package/src/server/test-data/worker-8/test.db +0 -0
  264. package/src/server/test-data/worker-9/agent-primary.json +12 -0
  265. package/src/server/test-data/worker-9/test.db +0 -0
  266. package/src/server/tests/cli/bin-entrypoint.test.ts +99 -0
  267. package/src/server/tests/cli/social.test.ts +83 -0
  268. package/src/server/tests/cron/social-inbound-followers.unit.test.ts +164 -0
  269. package/src/server/tests/cron/social-inbound-staleness.test.ts +193 -0
  270. package/src/server/tests/cron/social-outbound.test.ts +252 -0
  271. package/src/server/tests/endpoints/agent.test.ts +0 -16
  272. package/src/server/tests/lib/credential-field-schema.test.ts +448 -0
  273. package/src/server/tests/lib/project-scope.test.ts +49 -0
  274. package/src/server/tests/lib/social/create.test.ts +207 -0
  275. package/src/server/tests/lib/social/sign.test.ts +163 -0
  276. package/src/server/tests/lib/social/sync.test.ts +198 -0
  277. package/src/server/tests/mcp/server.test.ts +1 -3
  278. package/src/server/tests/mcp/tools.test.ts +219 -7
  279. package/src/server/tsconfig.tsbuildinfo +1 -1
  280. package/tsconfig.json +1 -0
  281. package/.next/server/chunks/2460.js +0 -7
  282. package/.next/server/chunks/5246.js +0 -1
  283. package/.next/static/chunks/3667-1db7bd03948e60df.js +0 -1
  284. package/.next/static/chunks/5442-b5bb869e832e8967.js +0 -1
  285. package/.next/static/chunks/6872-a8f1ad5fc35a1c35.js +0 -1
  286. package/.next/static/chunks/7394-4bdb1feefad1a74a.js +0 -1
  287. package/.next/static/chunks/7587-8542eae6e5139d27.js +0 -1
  288. package/.next/static/chunks/app/app-legacy-do-not-use/page-569fed5d1a2bfe79.js +0 -1
  289. package/.next/static/chunks/app/layout-af8d9969c7aeb758.js +0 -1
  290. package/.next/static/chunks/app/page-9bd0ec3ba4aa6cea.js +0 -1
  291. package/.next/static/css/88f92e1578b1e5d9.css +0 -3
  292. package/shared/agent-profile-schema.ts +0 -81
  293. package/src/internal/security/frontend-api-authorization-audit.md +0 -206
  294. package/src/server/lib/agent-profile-records.ts +0 -72
  295. /package/.next/static/{QPzVnl7GToqgYBq14V_iC → yEruVJH_cuht5hu5_1R00}/_buildManifest.js +0 -0
  296. /package/.next/static/{QPzVnl7GToqgYBq14V_iC → yEruVJH_cuht5hu5_1R00}/_ssgManifest.js +0 -0
@@ -23,21 +23,21 @@ model Log {
23
23
  }
24
24
 
25
25
  model HotWallet {
26
- id String @id @default(cuid())
27
- address String @unique
28
- encryptedPrivateKey String // Encrypted with in-memory seed
29
- tokenHash String // Which auth token owns this wallet
30
- coldWalletId String? // Agent ID (null = primary agent)
26
+ id String @id @default(cuid())
27
+ address String @unique
28
+ encryptedPrivateKey String // Encrypted with in-memory seed
29
+ tokenHash String // Which auth token owns this wallet
30
+ coldWalletId String? // Agent ID (null = primary agent)
31
31
 
32
32
  // Decorative fields
33
- name String?
34
- color String? // Hex color e.g. "#FF5733"
35
- description String?
36
- emoji String? // e.g. "🔥"
37
- hidden Boolean @default(false)
33
+ name String?
34
+ color String? // Hex color e.g. "#FF5733"
35
+ description String?
36
+ emoji String? // e.g. "🔥"
37
+ hidden Boolean @default(false)
38
38
 
39
- chain String @default("base")
40
- createdAt DateTime @default(now())
39
+ chain String @default("base")
40
+ createdAt DateTime @default(now())
41
41
 
42
42
  @@index([address])
43
43
  @@index([tokenHash])
@@ -46,16 +46,16 @@ model HotWallet {
46
46
  }
47
47
 
48
48
  model HumanAction {
49
- id String @id @default(cuid())
50
- type String // 'fund' | 'send' | 'agent_access' | 'action' | 'app:approve'
51
- fromTier String // 'cold' | 'hot' | 'temp' | 'system'
52
- toAddress String?
53
- amount String?
54
- chain String
55
- status String @default("pending") // 'pending' | 'approved' | 'rejected'
56
- createdAt DateTime @default(now())
57
- resolvedAt DateTime?
58
- metadata String? // JSON string for flexible metadata
49
+ id String @id @default(cuid())
50
+ type String // 'fund' | 'send' | 'agent_access' | 'action' | 'app:approve'
51
+ fromTier String // 'cold' | 'hot' | 'temp' | 'system'
52
+ toAddress String?
53
+ amount String?
54
+ chain String
55
+ status String @default("pending") // 'pending' | 'approved' | 'rejected'
56
+ createdAt DateTime @default(now())
57
+ resolvedAt DateTime?
58
+ metadata String? // JSON string for flexible metadata
59
59
  notification Notification?
60
60
 
61
61
  @@index([status])
@@ -63,34 +63,36 @@ model HumanAction {
63
63
  }
64
64
 
65
65
  model Notification {
66
- id String @id @default(cuid())
67
- type String // 'pending_approval' | 'info' | 'warning' | 'success' | 'error' | 'system'
68
- category String? // 'transaction' | 'security' | 'token' | 'wallet' | 'general'
69
- title String
70
- message String
71
- read Boolean @default(false)
72
- dismissed Boolean @default(false)
73
- actions String? // JSON: [{ id, label, type, action, endpoint, href }]
74
- metadata String? // JSON for flexible data
75
- humanActionId String? @unique
66
+ id String @id @default(cuid())
67
+ type String // 'pending_approval' | 'info' | 'warning' | 'success' | 'error' | 'system'
68
+ category String? // 'transaction' | 'security' | 'token' | 'wallet' | 'general' | 'social'
69
+ title String
70
+ message String
71
+ read Boolean @default(false)
72
+ dismissed Boolean @default(false)
73
+ actions String? // JSON: [{ id, label, type, action, endpoint, href }]
74
+ metadata String? // JSON for flexible data
75
+ humanActionId String? @unique
76
76
  humanAction HumanAction? @relation(fields: [humanActionId], references: [id])
77
- expiresAt DateTime?
78
- createdAt DateTime @default(now())
79
- updatedAt DateTime @updatedAt
80
- source String @default("system") // 'system' | 'agent' | 'user'
81
- agentId String?
77
+ hash String? @unique // dedup key for cron-generated notifications
78
+ expiresAt DateTime?
79
+ createdAt DateTime @default(now())
80
+ updatedAt DateTime @updatedAt
81
+ source String @default("system") // 'system' | 'agent' | 'user'
82
+ agentId String?
82
83
 
83
84
  @@index([read, dismissed])
84
85
  @@index([type])
85
86
  @@index([createdAt])
87
+ @@index([category, agentId])
86
88
  }
87
89
 
88
90
  // Stores all WebSocket events for debugging and audit trail
89
91
  model Event {
90
92
  id String @id @default(cuid())
91
- type String // e.g., 'request:created', 'token:revoked'
92
- source String // 'express' | 'nextjs'
93
- data String // JSON payload
93
+ type String // e.g., 'request:created', 'token:revoked'
94
+ source String // 'express' | 'nextjs'
95
+ data String // JSON payload
94
96
  timestamp DateTime @default(now())
95
97
  createdAt DateTime @default(now())
96
98
 
@@ -101,16 +103,16 @@ model Event {
101
103
 
102
104
  // Stores token metadata for UI/logs - actual signing stays in memory
103
105
  model AgentToken {
104
- id String @id @default(cuid())
105
- tokenHash String @unique // Hash of token for identification (not the token itself)
106
+ id String @id @default(cuid())
107
+ tokenHash String @unique // Hash of token for identification (not the token itself)
106
108
  agentId String
107
- limit Float // Max spending limit in ETH
108
- spent Float @default(0)
109
- permissions String // JSON array of permissions
109
+ limit Float // Max spending limit in ETH
110
+ spent Float @default(0)
111
+ permissions String // JSON array of permissions
110
112
  expiresAt DateTime
111
- isRevoked Boolean @default(false)
113
+ isRevoked Boolean @default(false)
112
114
  revokedAt DateTime?
113
- createdAt DateTime @default(now())
115
+ createdAt DateTime @default(now())
114
116
  lastUsedAt DateTime?
115
117
 
116
118
  @@index([agentId])
@@ -119,22 +121,22 @@ model AgentToken {
119
121
  }
120
122
 
121
123
  model CredentialAccessAudit {
122
- id String @id @default(cuid())
123
- timestamp DateTime @default(now())
124
- credentialId String
125
- agentId String
126
- action String
127
- allowed Boolean
128
- result String
129
- reasonCode String
130
- httpStatus Int
131
- tokenHash String?
132
- actorAgentId String?
133
- requestId String?
134
- actorType String
135
- projectScope String?
136
- sensitiveRead Boolean @default(true)
137
- metadata String?
124
+ id String @id @default(cuid())
125
+ timestamp DateTime @default(now())
126
+ credentialId String
127
+ agentId String
128
+ action String
129
+ allowed Boolean
130
+ result String
131
+ reasonCode String
132
+ httpStatus Int
133
+ tokenHash String?
134
+ actorAgentId String?
135
+ requestId String?
136
+ actorType String
137
+ projectScope String?
138
+ sensitiveRead Boolean @default(true)
139
+ metadata String?
138
140
 
139
141
  @@index([credentialId, timestamp(sort: Desc)])
140
142
  @@index([tokenHash, timestamp(sort: Desc)])
@@ -144,18 +146,18 @@ model CredentialAccessAudit {
144
146
 
145
147
  // Workspace system for programmatic dashboard control
146
148
  model Workspace {
147
- id String @id @default(cuid())
149
+ id String @id @default(cuid())
148
150
  name String
149
- slug String @unique
150
- icon String? // Lucide icon name
151
- emoji String? // Emoji character e.g. "🚀"
152
- color String? // Hex color code e.g. "#ff4d00"
153
- order Int @default(0)
154
- isDefault Boolean @default(false)
155
- isCloseable Boolean @default(true)
156
- createdAt DateTime @default(now())
157
- updatedAt DateTime @updatedAt
158
- apps WorkspaceApp[]
151
+ slug String @unique
152
+ icon String? // Lucide icon name
153
+ emoji String? // Emoji character e.g. "🚀"
154
+ color String? // Hex color code e.g. "#ff4d00"
155
+ order Int @default(0)
156
+ isDefault Boolean @default(false)
157
+ isCloseable Boolean @default(true)
158
+ createdAt DateTime @default(now())
159
+ updatedAt DateTime @updatedAt
160
+ apps WorkspaceApp[]
159
161
  theme WorkspaceTheme?
160
162
  }
161
163
 
@@ -164,18 +166,18 @@ model WorkspaceApp {
164
166
  workspaceId String
165
167
  workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
166
168
 
167
- appType String // 'wallets' | 'logs' | 'iframe' | 'installed:app-id'
168
- x Int @default(20)
169
- y Int @default(20)
170
- width Int @default(320)
171
- height Int @default(280)
172
- zIndex Int @default(10)
173
- isVisible Boolean @default(true)
174
- isLocked Boolean @default(false)
175
- config String? // JSON for iframe url, installed app props, etc.
169
+ appType String // 'wallets' | 'logs' | 'iframe' | 'installed:app-id'
170
+ x Int @default(20)
171
+ y Int @default(20)
172
+ width Int @default(320)
173
+ height Int @default(280)
174
+ zIndex Int @default(10)
175
+ isVisible Boolean @default(true)
176
+ isLocked Boolean @default(false)
177
+ config String? // JSON for iframe url, installed app props, etc.
176
178
 
177
- createdAt DateTime @default(now())
178
- updatedAt DateTime @updatedAt
179
+ createdAt DateTime @default(now())
180
+ updatedAt DateTime @updatedAt
179
181
 
180
182
  @@index([workspaceId])
181
183
  }
@@ -185,7 +187,7 @@ model ThemeConfig {
185
187
  id String @id @default("global")
186
188
  activeThemeId String @default("light")
187
189
  accentColor String @default("#ccff00")
188
- customThemes String? // JSON array of custom themes
190
+ customThemes String? // JSON array of custom themes
189
191
  createdAt DateTime @default(now())
190
192
  updatedAt DateTime @updatedAt
191
193
  }
@@ -195,23 +197,23 @@ model WorkspaceTheme {
195
197
  id String @id @default(cuid())
196
198
  workspaceId String @unique
197
199
  workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
198
- mode String? // 'light' | 'dark' - null means inherit from global
199
- accent String? // Hex color - null means inherit from global
200
- overrides String? // JSON for app palette overrides
200
+ mode String? // 'light' | 'dark' - null means inherit from global
201
+ accent String? // Hex color - null means inherit from global
202
+ overrides String? // JSON for app palette overrides
201
203
  createdAt DateTime @default(now())
202
204
  updatedAt DateTime @updatedAt
203
205
  }
204
206
 
205
207
  // API Keys for external services (Alchemy, etc.)
206
208
  model ApiKey {
207
- id String @id @default(cuid())
208
- service String // 'alchemy' | 'infura' | 'etherscan' | etc.
209
- name String // Display name e.g. "My Alchemy Key"
210
- key String // The actual API key (stored encrypted in production)
211
- metadata String? // JSON for service-specific config (e.g., allowed chains)
212
- isActive Boolean @default(true)
213
- createdAt DateTime @default(now())
214
- updatedAt DateTime @updatedAt
209
+ id String @id @default(cuid())
210
+ service String // 'alchemy' | 'infura' | 'etherscan' | etc.
211
+ name String // Display name e.g. "My Alchemy Key"
212
+ key String // The actual API key (stored encrypted in production)
213
+ metadata String? // JSON for service-specific config (e.g., allowed chains)
214
+ isActive Boolean @default(true)
215
+ createdAt DateTime @default(now())
216
+ updatedAt DateTime @updatedAt
215
217
 
216
218
  @@unique([service, name])
217
219
  @@index([service])
@@ -223,11 +225,11 @@ model Transaction {
223
225
  id String @id @default(cuid())
224
226
  walletAddress String
225
227
  txHash String?
226
- type String // 'send' | 'receive' | 'swap' | 'contract' | 'manual'
228
+ type String // 'send' | 'receive' | 'swap' | 'contract' | 'manual'
227
229
  status String @default("confirmed")
228
- amount String? // ETH amount
229
- tokenAddress String? // Token contract address if applicable
230
- tokenAmount String? // Token amount if applicable
230
+ amount String? // ETH amount
231
+ tokenAddress String? // Token contract address if applicable
232
+ tokenAmount String? // Token amount if applicable
231
233
  from String?
232
234
  to String?
233
235
  description String?
@@ -256,9 +258,9 @@ model TrackedAsset {
256
258
  lastBalanceAt DateTime?
257
259
  isHidden Boolean @default(false)
258
260
  chain String @default("base")
259
- poolAddress String? // Cached pool address for price lookup
260
- poolVersion String? // "v2" | "v3" | "v4"
261
- icon String? // Token icon URL
261
+ poolAddress String? // Cached pool address for price lookup
262
+ poolVersion String? // "v2" | "v3" | "v4"
263
+ icon String? // Token icon URL
262
264
  createdAt DateTime @default(now())
263
265
  updatedAt DateTime @updatedAt
264
266
 
@@ -282,7 +284,7 @@ model NativeBalance {
282
284
 
283
285
  // Cached native currency prices (ETH, SOL → USD)
284
286
  model NativePrice {
285
- currency String @id // "ETH" | "SOL"
287
+ currency String @id // "ETH" | "SOL"
286
288
  priceUsd String
287
289
  updatedAt DateTime @updatedAt
288
290
  }
@@ -295,32 +297,32 @@ model SyncState {
295
297
  lastSyncStatus String @default("idle")
296
298
  lastError String?
297
299
  syncCount Int @default(0)
298
- lastBlock String? // Block cursor for event scanning jobs (stringified bigint)
300
+ lastBlock String? // Block cursor for event scanning jobs (stringified bigint)
299
301
  updatedAt DateTime @updatedAt
300
302
  }
301
303
 
302
304
  // First-class strategy resources (template/headless + app-linked compatibility)
303
305
  model Strategy {
304
- id String @id @default(cuid())
306
+ id String @id @default(cuid())
305
307
  name String
306
308
  templateId String?
307
- mode String @default("headless") // 'headless' | 'app-linked'
308
- manifest String // JSON-encoded strategy manifest snapshot
309
- config String? // JSON-encoded user config
310
- state String? // JSON-encoded strategy state
311
- schedule String? // JSON-encoded schedule metadata (tier/cron/interval)
312
- permissions String @default("[]") // JSON-encoded permission list
313
- limits String? // JSON-encoded limits object
314
- enabled Boolean @default(false)
315
- status String @default("draft")
316
- createdBy String @default("human")
317
- provenance String? // JSON-encoded source/provenance metadata
318
- appId String? // legacy linkage when imported from a app
309
+ mode String @default("headless") // 'headless' | 'app-linked'
310
+ manifest String // JSON-encoded strategy manifest snapshot
311
+ config String? // JSON-encoded user config
312
+ state String? // JSON-encoded strategy state
313
+ schedule String? // JSON-encoded schedule metadata (tier/cron/interval)
314
+ permissions String @default("[]") // JSON-encoded permission list
315
+ limits String? // JSON-encoded limits object
316
+ enabled Boolean @default(false)
317
+ status String @default("draft")
318
+ createdBy String @default("human")
319
+ provenance String? // JSON-encoded source/provenance metadata
320
+ appId String? // legacy linkage when imported from a app
319
321
  lastTickAt DateTime?
320
322
  lastError String?
321
- errorCount Int @default(0)
322
- createdAt DateTime @default(now())
323
- updatedAt DateTime @updatedAt
323
+ errorCount Int @default(0)
324
+ createdAt DateTime @default(now())
325
+ updatedAt DateTime @updatedAt
324
326
  runs StrategyRun[]
325
327
 
326
328
  @@index([enabled, status])
@@ -337,7 +339,7 @@ model StrategyRun {
337
339
  endedAt DateTime?
338
340
  status String
339
341
  error String?
340
- metadata String? // JSON-encoded run metadata
342
+ metadata String? // JSON-encoded run metadata
341
343
 
342
344
  @@index([strategyId, startedAt])
343
345
  }
@@ -345,9 +347,9 @@ model StrategyRun {
345
347
  // Per-app persistent storage for third-party apps
346
348
  model AppStorage {
347
349
  id String @id @default(cuid())
348
- appId String
350
+ appId String
349
351
  key String
350
- value String // JSON stringified
352
+ value String // JSON stringified
351
353
  updatedAt DateTime @updatedAt
352
354
 
353
355
  @@unique([appId, key])
@@ -356,26 +358,26 @@ model AppStorage {
356
358
 
357
359
  // Cached token metadata for enriching on-chain events
358
360
  model TokenMetadata {
359
- id String @id @default(cuid())
360
- tokenAddress String
361
- chain String
362
- symbol String?
363
- name String?
364
- decimals Int @default(18)
365
- icon String?
366
- description String?
367
- priceUsd String? // Last known USD price (string for decimal precision)
368
- marketCap Float?
369
- fdv Float?
370
- liquidity Float? // DEX liquidity USD
371
- volume24h Float?
372
- dexId String? // Source DEX (e.g. "uniswap", "raydium")
373
- pairAddress String?
374
- websites String? // JSON-encoded string array
375
- socials String? // JSON-encoded [{type,url}] array
376
- lastAccessedAt DateTime @default(now())
377
- lastVerifiedAt DateTime?
378
- updatedAt DateTime @updatedAt
361
+ id String @id @default(cuid())
362
+ tokenAddress String
363
+ chain String
364
+ symbol String?
365
+ name String?
366
+ decimals Int @default(18)
367
+ icon String?
368
+ description String?
369
+ priceUsd String? // Last known USD price (string for decimal precision)
370
+ marketCap Float?
371
+ fdv Float?
372
+ liquidity Float? // DEX liquidity USD
373
+ volume24h Float?
374
+ dexId String? // Source DEX (e.g. "uniswap", "raydium")
375
+ pairAddress String?
376
+ websites String? // JSON-encoded string array
377
+ socials String? // JSON-encoded [{type,url}] array
378
+ lastAccessedAt DateTime @default(now())
379
+ lastVerifiedAt DateTime?
380
+ updatedAt DateTime @updatedAt
379
381
 
380
382
  @@unique([tokenAddress, chain])
381
383
  @@index([tokenAddress])
@@ -383,13 +385,13 @@ model TokenMetadata {
383
385
 
384
386
  // Cached DEX pool metadata for enriching swap events
385
387
  model PoolMetadata {
386
- id String @id @default(cuid())
387
- poolAddress String
388
- chain String
389
- token0 String?
390
- token1 String?
391
- fee Int?
392
- dex String? // "uniswap_v2" | "uniswap_v3" | "uniswap_v4"
388
+ id String @id @default(cuid())
389
+ poolAddress String
390
+ chain String
391
+ token0 String?
392
+ token1 String?
393
+ fee Int?
394
+ dex String? // "uniswap_v2" | "uniswap_v3" | "uniswap_v4"
393
395
 
394
396
  @@unique([poolAddress, chain])
395
397
  @@index([poolAddress])
@@ -397,26 +399,26 @@ model PoolMetadata {
397
399
 
398
400
  // Address book for labeling external addresses
399
401
  model AddressLabel {
400
- id String @id @default(cuid())
401
- address String @unique
402
- label String
403
- emoji String?
404
- color String?
405
- notes String?
406
- createdBy String @default("human")
407
- createdAt DateTime @default(now())
408
- updatedAt DateTime @updatedAt
402
+ id String @id @default(cuid())
403
+ address String @unique
404
+ label String
405
+ emoji String?
406
+ color String?
407
+ notes String?
408
+ createdBy String @default("human")
409
+ createdAt DateTime @default(now())
410
+ updatedAt DateTime @updatedAt
409
411
 
410
412
  @@index([label])
411
413
  }
412
414
 
413
415
  // Centralized system defaults (key-value store for configurable limits, permissions, TTLs, etc.)
414
416
  model SystemDefault {
415
- key String @id // e.g. "limits.fund", "permissions.default"
416
- value String // JSON-encoded value
417
- type String // Category: "permissions" | "financial" | "ttl" | "rate_limit" | "ai_safety" | "launch" | "app" | "swap"
418
- label String // Human-readable label for dashboard
419
- description String? // Optional description
417
+ key String @id // e.g. "limits.fund", "permissions.default"
418
+ value String // JSON-encoded value
419
+ type String // Category: "permissions" | "financial" | "ttl" | "rate_limit" | "ai_safety" | "launch" | "app" | "swap"
420
+ label String // Human-readable label for dashboard
421
+ description String? // Optional description
420
422
  updatedAt DateTime @updatedAt
421
423
 
422
424
  @@index([type])
@@ -424,15 +426,15 @@ model SystemDefault {
424
426
 
425
427
  // WebAuthn passkey credentials for biometric agent unlock
426
428
  model Passkey {
427
- id String @id @default(cuid())
428
- credentialId String @unique // base64url WebAuthn credential ID
429
- publicKey Bytes // COSE public key (base64url ↔ Uint8Array conversion needed)
430
- counter Int @default(0) // signature counter (replay/clone detection)
431
- transports String @default("[]") // JSON array of transport hints
432
- rpId String // relying party ID (e.g. "localhost")
433
- aaguid String @default("") // authenticator AAGUID
434
- createdAt DateTime @default(now())
435
- lastUsedAt DateTime?
429
+ id String @id @default(cuid())
430
+ credentialId String @unique // base64url WebAuthn credential ID
431
+ publicKey Bytes // COSE public key (base64url ↔ Uint8Array conversion needed)
432
+ counter Int @default(0) // signature counter (replay/clone detection)
433
+ transports String @default("[]") // JSON array of transport hints
434
+ rpId String // relying party ID (e.g. "localhost")
435
+ aaguid String @default("") // authenticator AAGUID
436
+ createdAt DateTime @default(now())
437
+ lastUsedAt DateTime?
436
438
 
437
439
  @@index([rpId])
438
440
  }
@@ -440,8 +442,101 @@ model Passkey {
440
442
  // Global app configuration (singleton)
441
443
  model AppConfig {
442
444
  id String @id @default("global")
443
- chainConfig String? // JSON: { base: { rpc: "...", chainId: 8453 }, ... }
444
- adapterConfig String? // JSON: { enabled: true, adapters: [{ type, enabled, config }] }
445
+ chainConfig String? // JSON: { base: { rpc: "...", chainId: 8453 }, ... }
446
+ adapterConfig String? // JSON: { enabled: true, adapters: [{ type, enabled, config }] }
445
447
  createdAt DateTime @default(now())
446
448
  updatedAt DateTime @updatedAt
447
449
  }
450
+
451
+ // Agent profile — autofill data + hub identity.
452
+ // Replaces the old agent-profiles.json file.
453
+ // One row per agent. auraId is null until hub registration.
454
+ model AgentProfile {
455
+ id String @id @default(cuid())
456
+ agentId String @unique // local agent ID (e.g. "primary")
457
+ auraId Int? @unique // hub-assigned numeric ID (null until registered)
458
+ publicKeyHex String? @unique // ED25519 public key (hex, derived from mnemonic)
459
+ email String?
460
+ phone String?
461
+ address String? // mailing/physical address
462
+ profileImage String?
463
+ attributes String? // JSON stringified Record<string, string>
464
+ inboundSeq Int? // last global event log sequence number
465
+ inboundMode String? // "incremental" | "snapshot"
466
+ createdAt DateTime @default(now())
467
+ updatedAt DateTime @updatedAt
468
+ }
469
+
470
+ // Hub subscriptions — one row per (agent, hub) pair.
471
+ // Holds per-hub sync cursor and registration state.
472
+ model HubSubscription {
473
+ id String @id @default(cuid())
474
+ agentId String // local agent ID (e.g. "primary")
475
+ hubUrl String // normalized base URL, e.g. "https://hub.auramaxx.com"
476
+ frontendUrl String? // hub frontend URL for iframe embed, e.g. "https://hub.auramaxx.com:3000"
477
+ label String? // user-facing display name
478
+ auraId Int? // auraId assigned by THIS hub (null until registered)
479
+ inboundSeq Int? // per-hub event cursor
480
+ inboundMode String? // "incremental" | "snapshot"
481
+ joinedAt DateTime @default(now())
482
+ updatedAt DateTime @updatedAt
483
+
484
+ @@unique([agentId, hubUrl])
485
+ @@index([agentId])
486
+ }
487
+
488
+ // Outbound: messages authored by this agent.
489
+ // Source of truth. Hub sync is distribution.
490
+ model SocialMessage {
491
+ id String @id @default(cuid())
492
+ agentId String // which vault agent authored this
493
+ hash String @unique // BLAKE3 hash (hex, 64 chars)
494
+ type String // post_add | post_remove | reaction_add | reaction_remove | link_add | link_remove | user_data_add
495
+ body String // JSON-encoded message body
496
+ timestamp Int // message timestamp (ms since epoch)
497
+ network String @default("mainnet") // mainnet | testnet
498
+ signature String // ED25519 signature (hex, 128 chars)
499
+ signer String // ED25519 public key (hex, 64 chars)
500
+ hubUrl String @default("") // target hub URL; "" = default hub
501
+
502
+ // Sync state
503
+ syncStatus String @default("pending") // pending | accepted | duplicate | rejected | failed
504
+ syncCode String? // hub response code
505
+ syncDetail String? // hub response detail
506
+ syncedAt DateTime? // when hub accepted
507
+ attempts Int @default(0) // sync retry count
508
+ nextRetryAt DateTime? // backoff timer
509
+
510
+ createdAt DateTime @default(now())
511
+ updatedAt DateTime @updatedAt
512
+
513
+ @@index([agentId, createdAt])
514
+ @@index([agentId, type])
515
+ @@index([syncStatus, nextRetryAt])
516
+ @@index([hubUrl, syncStatus, nextRetryAt])
517
+ @@index([type, createdAt])
518
+ }
519
+
520
+ // Inbound: messages from other agents, cached locally.
521
+ // Pulled from hub via global event log or snapshot.
522
+ // All reads (feed, notifications, follower counts) query this table.
523
+ model InboundMessage {
524
+ id String @id @default(cuid())
525
+ agentId String // which local agent this is cached for
526
+ hash String // BLAKE3 hash from the original message
527
+ hubUrl String @default("") // source hub URL; "" = default hub
528
+ authorAuraId Int @default(0) // who wrote it (0 = unknown, resolved by pubkey)
529
+ authorPublicKey String @default("") // author's ED25519 public key (hex)
530
+ type String // post_add, reaction_add, link_add, etc.
531
+ body String // JSON-encoded message body
532
+ timestamp Int // original message timestamp
533
+
534
+ createdAt DateTime @default(now())
535
+
536
+ @@unique([hash, hubUrl])
537
+ @@index([agentId, type])
538
+ @@index([agentId, hubUrl, type])
539
+ @@index([agentId, timestamp])
540
+ @@index([authorAuraId])
541
+ @@index([authorPublicKey])
542
+ }
@@ -258,3 +258,13 @@ export function getCredentialFieldValue(
258
258
  const canonicalKey = canonicalizeCredentialFieldKey(type, key);
259
259
  return normalized.find((field) => field.key === canonicalKey)?.value;
260
260
  }
261
+
262
+ /**
263
+ * Look up the schema spec for a given credential type + field key.
264
+ * Returns the CredentialFieldSpec if found, or undefined for unknown types/keys.
265
+ */
266
+ export function getCredentialFieldSpec(type: string, key: string): CredentialFieldSpec | undefined {
267
+ if (!isCredentialType(type)) return undefined;
268
+ const canonicalKey = canonicalizeCredentialFieldKey(type, key);
269
+ return CREDENTIAL_FIELD_SCHEMA[type].find((field) => field.key === canonicalKey);
270
+ }