@pithy-sh/core 0.13.0 → 0.14.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 (354) hide show
  1. package/README.md +54 -0
  2. package/dist/audit/auditEvent.js +1 -1
  3. package/dist/audit/chain.d.ts +289 -0
  4. package/dist/audit/chain.d.ts.map +1 -0
  5. package/dist/audit/chain.js +400 -0
  6. package/dist/audit/citations.d.ts +52 -0
  7. package/dist/audit/citations.d.ts.map +1 -0
  8. package/dist/audit/citations.js +13 -0
  9. package/dist/capability/bindings.d.ts +22 -0
  10. package/dist/capability/bindings.d.ts.map +1 -1
  11. package/dist/capability/bindings.js +32 -2
  12. package/dist/capability/capability.d.ts +123 -16
  13. package/dist/capability/capability.d.ts.map +1 -1
  14. package/dist/capability/capability.js +17 -2
  15. package/dist/capability/erasure.d.ts +75 -0
  16. package/dist/capability/erasure.d.ts.map +1 -0
  17. package/dist/capability/erasure.js +2 -0
  18. package/dist/capability/manifest.d.ts +5 -0
  19. package/dist/capability/manifest.d.ts.map +1 -1
  20. package/dist/capability/personColumns.d.ts +28 -0
  21. package/dist/capability/personColumns.d.ts.map +1 -0
  22. package/dist/capability/personColumns.js +66 -0
  23. package/dist/capability/personRows.d.ts +62 -0
  24. package/dist/capability/personRows.d.ts.map +1 -0
  25. package/dist/capability/personRows.js +59 -0
  26. package/dist/capability/purge.d.ts +86 -19
  27. package/dist/capability/purge.d.ts.map +1 -1
  28. package/dist/capability/purge.js +83 -5
  29. package/dist/capability/settings.d.ts +10 -0
  30. package/dist/capability/settings.d.ts.map +1 -1
  31. package/dist/capability/vectorIndex.d.ts +36 -0
  32. package/dist/capability/vectorIndex.d.ts.map +1 -0
  33. package/dist/capability/vectorIndex.js +25 -0
  34. package/dist/cli/commandCatalog.generated.d.ts +433 -3
  35. package/dist/cli/commandCatalog.generated.d.ts.map +1 -1
  36. package/dist/cli/commandCatalog.generated.js +449 -2
  37. package/dist/cli/commandFacts.d.ts +8 -5
  38. package/dist/cli/commandFacts.d.ts.map +1 -1
  39. package/dist/cli/commandFacts.js +12 -3
  40. package/dist/consent/purpose.d.ts +70 -0
  41. package/dist/consent/purpose.d.ts.map +1 -0
  42. package/dist/consent/purpose.js +97 -0
  43. package/dist/consent/reader.d.ts +99 -0
  44. package/dist/consent/reader.d.ts.map +1 -0
  45. package/dist/consent/reader.js +33 -0
  46. package/dist/controlPlane/audit/actions.d.ts +15 -4
  47. package/dist/controlPlane/audit/actions.d.ts.map +1 -1
  48. package/dist/controlPlane/audit/actions.js +16 -5
  49. package/dist/controlPlane/capability.d.ts +10 -0
  50. package/dist/controlPlane/capability.d.ts.map +1 -1
  51. package/dist/controlPlane/capability.js +56 -8
  52. package/dist/controlPlane/context.d.ts +4 -0
  53. package/dist/controlPlane/context.d.ts.map +1 -1
  54. package/dist/controlPlane/context.js +3 -2
  55. package/dist/controlPlane/data/connection.d.ts +21 -2
  56. package/dist/controlPlane/data/connection.d.ts.map +1 -1
  57. package/dist/controlPlane/data/connection.js +13 -4
  58. package/dist/controlPlane/data/connections.d.ts +94 -0
  59. package/dist/controlPlane/data/connections.d.ts.map +1 -0
  60. package/dist/controlPlane/data/connections.js +151 -0
  61. package/dist/controlPlane/data/hold.d.ts +46 -0
  62. package/dist/controlPlane/data/hold.d.ts.map +1 -0
  63. package/dist/controlPlane/data/hold.js +36 -0
  64. package/dist/controlPlane/data/oidcTrust.d.ts +122 -0
  65. package/dist/controlPlane/data/oidcTrust.d.ts.map +1 -0
  66. package/dist/controlPlane/data/oidcTrust.js +173 -0
  67. package/dist/controlPlane/data/tables.d.ts +4 -0
  68. package/dist/controlPlane/data/tables.d.ts.map +1 -1
  69. package/dist/controlPlane/data/tables.js +9 -4
  70. package/dist/controlPlane/data/trustFirstCall.d.ts +16 -0
  71. package/dist/controlPlane/data/trustFirstCall.d.ts.map +1 -0
  72. package/dist/controlPlane/data/trustFirstCall.js +25 -0
  73. package/dist/controlPlane/discovery/adminRoute.d.ts +165 -2
  74. package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -1
  75. package/dist/controlPlane/discovery/adminRoute.js +32 -8
  76. package/dist/controlPlane/discovery/routeInput.d.ts +23 -0
  77. package/dist/controlPlane/discovery/routeInput.d.ts.map +1 -0
  78. package/dist/controlPlane/discovery/routeInput.js +80 -0
  79. package/dist/controlPlane/discovery/toolName.d.ts +21 -0
  80. package/dist/controlPlane/discovery/toolName.d.ts.map +1 -0
  81. package/dist/controlPlane/discovery/toolName.js +25 -0
  82. package/dist/controlPlane/erasure/attest.d.ts +78 -0
  83. package/dist/controlPlane/erasure/attest.d.ts.map +1 -0
  84. package/dist/controlPlane/erasure/attest.js +164 -0
  85. package/dist/controlPlane/erasure/read.d.ts +39 -0
  86. package/dist/controlPlane/erasure/read.d.ts.map +1 -0
  87. package/dist/controlPlane/erasure/read.js +140 -0
  88. package/dist/controlPlane/error/errors.d.ts +61 -2
  89. package/dist/controlPlane/error/errors.d.ts.map +1 -1
  90. package/dist/controlPlane/error/errors.js +13 -0
  91. package/dist/controlPlane/evidence/derive.d.ts +124 -0
  92. package/dist/controlPlane/evidence/derive.d.ts.map +1 -0
  93. package/dist/controlPlane/evidence/derive.js +343 -0
  94. package/dist/controlPlane/evidence/mapping.d.ts +85 -0
  95. package/dist/controlPlane/evidence/mapping.d.ts.map +1 -0
  96. package/dist/controlPlane/evidence/mapping.js +114 -0
  97. package/dist/controlPlane/evidence/pack.d.ts +46 -0
  98. package/dist/controlPlane/evidence/pack.d.ts.map +1 -0
  99. package/dist/controlPlane/evidence/pack.js +124 -0
  100. package/dist/controlPlane/http/connections.d.ts +96 -0
  101. package/dist/controlPlane/http/connections.d.ts.map +1 -0
  102. package/dist/controlPlane/http/connections.js +109 -0
  103. package/dist/controlPlane/http/guard.d.ts +23 -2
  104. package/dist/controlPlane/http/guard.d.ts.map +1 -1
  105. package/dist/controlPlane/http/guard.js +69 -12
  106. package/dist/controlPlane/http/handlers.d.ts +212 -10
  107. package/dist/controlPlane/http/handlers.d.ts.map +1 -1
  108. package/dist/controlPlane/http/handlers.js +117 -26
  109. package/dist/controlPlane/http/holds.d.ts +57 -0
  110. package/dist/controlPlane/http/holds.d.ts.map +1 -0
  111. package/dist/controlPlane/http/holds.js +98 -0
  112. package/dist/controlPlane/http/presence.d.ts +27 -0
  113. package/dist/controlPlane/http/presence.d.ts.map +1 -0
  114. package/dist/controlPlane/http/presence.js +67 -0
  115. package/dist/controlPlane/http/processing.d.ts +73 -0
  116. package/dist/controlPlane/http/processing.d.ts.map +1 -0
  117. package/dist/controlPlane/http/processing.js +17 -0
  118. package/dist/controlPlane/http/responses.d.ts +927 -3
  119. package/dist/controlPlane/http/responses.d.ts.map +1 -1
  120. package/dist/controlPlane/http/responses.js +283 -7
  121. package/dist/controlPlane/http/routes.d.ts +12 -2
  122. package/dist/controlPlane/http/routes.d.ts.map +1 -1
  123. package/dist/controlPlane/http/routes.js +182 -5
  124. package/dist/controlPlane/http/schemas.d.ts +63 -0
  125. package/dist/controlPlane/http/schemas.d.ts.map +1 -1
  126. package/dist/controlPlane/http/schemas.js +39 -1
  127. package/dist/controlPlane/http/verify.d.ts.map +1 -1
  128. package/dist/controlPlane/http/verify.js +13 -1
  129. package/dist/controlPlane/http/verifyTrust.d.ts +76 -0
  130. package/dist/controlPlane/http/verifyTrust.d.ts.map +1 -0
  131. package/dist/controlPlane/http/verifyTrust.js +75 -0
  132. package/dist/controlPlane/migrations/0004_connection_trusts.d.ts +15 -0
  133. package/dist/controlPlane/migrations/0004_connection_trusts.d.ts.map +1 -0
  134. package/dist/controlPlane/migrations/0004_connection_trusts.js +23 -0
  135. package/dist/controlPlane/migrations/0005_holds.d.ts +12 -0
  136. package/dist/controlPlane/migrations/0005_holds.d.ts.map +1 -0
  137. package/dist/controlPlane/migrations/0005_holds.js +26 -0
  138. package/dist/controlPlane/processing/derive.d.ts +77 -0
  139. package/dist/controlPlane/processing/derive.d.ts.map +1 -0
  140. package/dist/controlPlane/processing/derive.js +206 -0
  141. package/dist/controlPlane/processing/read.d.ts +10 -0
  142. package/dist/controlPlane/processing/read.d.ts.map +1 -0
  143. package/dist/controlPlane/processing/read.js +89 -0
  144. package/dist/controlPlane/scope/kind.d.ts +46 -0
  145. package/dist/controlPlane/scope/kind.d.ts.map +1 -0
  146. package/dist/controlPlane/scope/kind.js +52 -0
  147. package/dist/controlPlane/scope/scope.d.ts +58 -3
  148. package/dist/controlPlane/scope/scope.d.ts.map +1 -1
  149. package/dist/controlPlane/scope/scope.js +59 -4
  150. package/dist/controlPlane/token/jws.js +1 -1
  151. package/dist/controlPlane/token/mint.js +1 -1
  152. package/dist/controlPlane/wire.d.ts +23 -0
  153. package/dist/controlPlane/wire.d.ts.map +1 -1
  154. package/dist/controlPlane/wire.js +24 -1
  155. package/dist/createBackend.d.ts +13 -0
  156. package/dist/createBackend.d.ts.map +1 -1
  157. package/dist/createBackend.js +11 -3
  158. package/dist/createEntrypoint.d.ts +7 -0
  159. package/dist/createEntrypoint.d.ts.map +1 -1
  160. package/dist/createEntrypoint.js +4 -0
  161. package/dist/error/http.d.ts +168 -0
  162. package/dist/error/http.d.ts.map +1 -1
  163. package/dist/error/payload.d.ts +336 -0
  164. package/dist/error/payload.d.ts.map +1 -1
  165. package/dist/error/payload.js +112 -0
  166. package/dist/error/pithyError.d.ts +22 -0
  167. package/dist/error/pithyError.d.ts.map +1 -1
  168. package/dist/error/pithyError.js +31 -1
  169. package/dist/http/routeSpec.d.ts +46 -1
  170. package/dist/http/routeSpec.d.ts.map +1 -1
  171. package/dist/http/routeSpec.js +39 -5
  172. package/dist/http/verification.d.ts.map +1 -1
  173. package/dist/http/verification.js +1 -1
  174. package/dist/i18n/translator.d.ts +2 -1
  175. package/dist/i18n/translator.d.ts.map +1 -1
  176. package/dist/index.d.ts +1 -1
  177. package/dist/index.d.ts.map +1 -1
  178. package/dist/index.js +3 -3
  179. package/dist/logger/record.d.ts +98 -0
  180. package/dist/logger/record.d.ts.map +1 -1
  181. package/dist/mcp/annotations.d.ts +20 -0
  182. package/dist/mcp/annotations.d.ts.map +1 -0
  183. package/dist/mcp/annotations.js +23 -0
  184. package/dist/mcp/tools.d.ts +75 -0
  185. package/dist/mcp/tools.d.ts.map +1 -0
  186. package/dist/mcp/tools.js +118 -0
  187. package/dist/openapi/document.d.ts.map +1 -1
  188. package/dist/openapi/document.js +8 -26
  189. package/dist/openapi/operations.d.ts +35 -0
  190. package/dist/openapi/operations.d.ts.map +1 -0
  191. package/dist/openapi/operations.js +37 -0
  192. package/dist/presence/channel.d.ts +11 -0
  193. package/dist/presence/channel.d.ts.map +1 -0
  194. package/dist/presence/channel.js +65 -0
  195. package/dist/presence/declaration.d.ts +154 -0
  196. package/dist/presence/declaration.d.ts.map +1 -0
  197. package/dist/presence/declaration.js +164 -0
  198. package/dist/presence/durableObject.d.ts +61 -0
  199. package/dist/presence/durableObject.d.ts.map +1 -0
  200. package/dist/presence/durableObject.js +257 -0
  201. package/dist/presence/frames.d.ts +166 -0
  202. package/dist/presence/frames.d.ts.map +1 -0
  203. package/dist/presence/frames.js +90 -0
  204. package/dist/presence/http/guard.d.ts +11 -0
  205. package/dist/presence/http/guard.d.ts.map +1 -0
  206. package/dist/presence/http/guard.js +20 -0
  207. package/dist/presence/http/responses.d.ts +31 -0
  208. package/dist/presence/http/responses.d.ts.map +1 -0
  209. package/dist/presence/http/responses.js +34 -0
  210. package/dist/presence/http/routes.d.ts +24 -0
  211. package/dist/presence/http/routes.d.ts.map +1 -0
  212. package/dist/presence/http/routes.js +127 -0
  213. package/dist/presence/http/schemas.d.ts +29 -0
  214. package/dist/presence/http/schemas.d.ts.map +1 -0
  215. package/dist/presence/http/schemas.js +28 -0
  216. package/dist/presence/names.d.ts +23 -0
  217. package/dist/presence/names.d.ts.map +1 -0
  218. package/dist/presence/names.js +22 -0
  219. package/dist/presence/room.d.ts +95 -0
  220. package/dist/presence/room.d.ts.map +1 -0
  221. package/dist/presence/room.js +105 -0
  222. package/dist/presence/ticket.d.ts +55 -0
  223. package/dist/presence/ticket.d.ts.map +1 -0
  224. package/dist/presence/ticket.js +109 -0
  225. package/dist/privacy/classify.js +1 -1
  226. package/dist/privacy/encrypted.js +1 -1
  227. package/dist/processing/activity.d.ts +134 -0
  228. package/dist/processing/activity.d.ts.map +1 -0
  229. package/dist/processing/activity.js +161 -0
  230. package/dist/processing/composed.d.ts +18 -0
  231. package/dist/processing/composed.d.ts.map +1 -0
  232. package/dist/processing/composed.js +28 -0
  233. package/dist/processing/vocabulary.d.ts +26 -0
  234. package/dist/processing/vocabulary.d.ts.map +1 -0
  235. package/dist/processing/vocabulary.js +35 -0
  236. package/dist/queue/consumer.d.ts +59 -0
  237. package/dist/queue/consumer.d.ts.map +1 -0
  238. package/dist/queue/consumer.js +46 -0
  239. package/dist/retention/composed.d.ts +37 -0
  240. package/dist/retention/composed.d.ts.map +1 -0
  241. package/dist/retention/composed.js +66 -0
  242. package/dist/retention/holds.d.ts +61 -0
  243. package/dist/retention/holds.d.ts.map +1 -0
  244. package/dist/retention/holds.js +107 -0
  245. package/dist/retention/holdsPurge.d.ts +22 -0
  246. package/dist/retention/holdsPurge.d.ts.map +1 -0
  247. package/dist/retention/holdsPurge.js +50 -0
  248. package/dist/retention/policy.d.ts +132 -0
  249. package/dist/retention/policy.d.ts.map +1 -0
  250. package/dist/retention/policy.js +197 -0
  251. package/dist/session/rotated.d.ts +34 -0
  252. package/dist/session/rotated.d.ts.map +1 -0
  253. package/dist/session/rotated.js +25 -0
  254. package/dist/test-utils/connectionFixtures.d.ts +13 -0
  255. package/dist/test-utils/connectionFixtures.d.ts.map +1 -0
  256. package/dist/test-utils/connectionFixtures.js +58 -0
  257. package/dist/test-utils/interleave.d.ts +12 -0
  258. package/dist/test-utils/interleave.d.ts.map +1 -0
  259. package/dist/test-utils/interleave.js +26 -0
  260. package/dist/testWorker.d.ts +8 -0
  261. package/dist/testWorker.d.ts.map +1 -0
  262. package/dist/testWorker.js +9 -0
  263. package/dist/version.generated.d.ts +1 -1
  264. package/dist/version.generated.js +1 -1
  265. package/dist/workflow/dispatchRoute.js +1 -1
  266. package/package.json +1 -1
  267. package/src/audit/auditEvent.ts +1 -1
  268. package/src/audit/chain.ts +551 -0
  269. package/src/audit/citations.ts +63 -0
  270. package/src/capability/bindings.ts +61 -0
  271. package/src/capability/capability.ts +156 -19
  272. package/src/capability/erasure.ts +82 -0
  273. package/src/capability/personColumns.ts +83 -0
  274. package/src/capability/personRows.ts +125 -0
  275. package/src/capability/purge.ts +158 -21
  276. package/src/capability/settings.ts +7 -0
  277. package/src/capability/vectorIndex.ts +60 -0
  278. package/src/cli/commandCatalog.generated.ts +482 -2
  279. package/src/cli/commandFacts.ts +12 -3
  280. package/src/cloudflare-test.d.ts +3 -1
  281. package/src/consent/purpose.ts +160 -0
  282. package/src/consent/reader.ts +134 -0
  283. package/src/controlPlane/audit/actions.ts +15 -4
  284. package/src/controlPlane/capability.ts +99 -20
  285. package/src/controlPlane/context.ts +10 -2
  286. package/src/controlPlane/data/connection.ts +16 -2
  287. package/src/controlPlane/data/connections.ts +231 -0
  288. package/src/controlPlane/data/hold.ts +52 -0
  289. package/src/controlPlane/data/oidcTrust.ts +249 -0
  290. package/src/controlPlane/data/tables.ts +7 -0
  291. package/src/controlPlane/data/trustFirstCall.ts +37 -0
  292. package/src/controlPlane/discovery/adminRoute.ts +71 -9
  293. package/src/controlPlane/discovery/routeInput.ts +86 -0
  294. package/src/controlPlane/discovery/toolName.ts +23 -0
  295. package/src/controlPlane/erasure/attest.ts +205 -0
  296. package/src/controlPlane/erasure/read.ts +169 -0
  297. package/src/controlPlane/error/errors.ts +69 -2
  298. package/src/controlPlane/evidence/derive.ts +426 -0
  299. package/src/controlPlane/evidence/mapping.ts +118 -0
  300. package/src/controlPlane/evidence/pack.ts +190 -0
  301. package/src/controlPlane/http/connections.ts +129 -0
  302. package/src/controlPlane/http/guard.ts +118 -9
  303. package/src/controlPlane/http/handlers.ts +172 -40
  304. package/src/controlPlane/http/holds.ts +108 -0
  305. package/src/controlPlane/http/presence.ts +71 -0
  306. package/src/controlPlane/http/processing.ts +19 -0
  307. package/src/controlPlane/http/responses.ts +590 -7
  308. package/src/controlPlane/http/routes.ts +302 -3
  309. package/src/controlPlane/http/schemas.ts +126 -0
  310. package/src/controlPlane/http/verify.ts +19 -2
  311. package/src/controlPlane/http/verifyTrust.ts +176 -0
  312. package/src/controlPlane/migrations/0004_connection_trusts.ts +30 -0
  313. package/src/controlPlane/migrations/0005_holds.ts +40 -0
  314. package/src/controlPlane/processing/derive.ts +359 -0
  315. package/src/controlPlane/processing/read.ts +102 -0
  316. package/src/controlPlane/scope/kind.ts +63 -0
  317. package/src/controlPlane/scope/scope.ts +65 -3
  318. package/src/controlPlane/wire.ts +26 -0
  319. package/src/createBackend.ts +31 -6
  320. package/src/createEntrypoint.ts +17 -0
  321. package/src/error/payload.ts +234 -0
  322. package/src/error/pithyError.ts +42 -0
  323. package/src/http/routeSpec.ts +75 -5
  324. package/src/http/verification.ts +3 -1
  325. package/src/i18n/translator.ts +2 -1
  326. package/src/index.ts +2 -0
  327. package/src/mcp/annotations.ts +38 -0
  328. package/src/mcp/tools.ts +220 -0
  329. package/src/openapi/document.ts +8 -28
  330. package/src/openapi/operations.ts +62 -0
  331. package/src/presence/channel.ts +46 -0
  332. package/src/presence/declaration.ts +283 -0
  333. package/src/presence/durableObject.ts +287 -0
  334. package/src/presence/frames.ts +153 -0
  335. package/src/presence/http/guard.ts +23 -0
  336. package/src/presence/http/responses.ts +63 -0
  337. package/src/presence/http/routes.ts +165 -0
  338. package/src/presence/http/schemas.ts +39 -0
  339. package/src/presence/names.ts +45 -0
  340. package/src/presence/room.ts +145 -0
  341. package/src/presence/ticket.ts +145 -0
  342. package/src/processing/activity.ts +289 -0
  343. package/src/processing/composed.ts +33 -0
  344. package/src/processing/vocabulary.ts +43 -0
  345. package/src/queue/consumer.ts +104 -0
  346. package/src/retention/composed.ts +75 -0
  347. package/src/retention/holds.ts +175 -0
  348. package/src/retention/holdsPurge.ts +50 -0
  349. package/src/retention/policy.ts +305 -0
  350. package/src/session/rotated.ts +53 -0
  351. package/src/test-utils/connectionFixtures.ts +58 -0
  352. package/src/test-utils/interleave.ts +31 -0
  353. package/src/testWorker.ts +13 -0
  354. package/src/version.generated.ts +1 -1
@@ -121,6 +121,13 @@ export declare const LogRecord: z.ZodObject<{
121
121
  detail: z.ZodOptional<z.ZodString>;
122
122
  code: z.ZodLiteral<"auth/account_deleted">;
123
123
  status: z.ZodLiteral<403>;
124
+ }, z.core.$strip>, z.ZodObject<{
125
+ message: z.ZodString;
126
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
127
+ action: z.ZodOptional<z.ZodString>;
128
+ detail: z.ZodOptional<z.ZodString>;
129
+ code: z.ZodLiteral<"auth/handoff_invalid">;
130
+ status: z.ZodLiteral<400>;
124
131
  }, z.core.$strip>, z.ZodObject<{
125
132
  message: z.ZodString;
126
133
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -198,6 +205,20 @@ export declare const LogRecord: z.ZodObject<{
198
205
  detail: z.ZodOptional<z.ZodString>;
199
206
  code: z.ZodLiteral<"core/webhook_unverified">;
200
207
  status: z.ZodLiteral<401>;
208
+ }, z.core.$strip>, z.ZodObject<{
209
+ message: z.ZodString;
210
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
211
+ action: z.ZodOptional<z.ZodString>;
212
+ detail: z.ZodOptional<z.ZodString>;
213
+ code: z.ZodLiteral<"core/presence_ticket_invalid">;
214
+ status: z.ZodLiteral<401>;
215
+ }, z.core.$strip>, z.ZodObject<{
216
+ message: z.ZodString;
217
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
218
+ action: z.ZodOptional<z.ZodString>;
219
+ detail: z.ZodOptional<z.ZodString>;
220
+ code: z.ZodLiteral<"core/presence_room_full">;
221
+ status: z.ZodLiteral<409>;
201
222
  }, z.core.$strip>, z.ZodObject<{
202
223
  message: z.ZodString;
203
224
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -527,6 +548,27 @@ export declare const LogRecord: z.ZodObject<{
527
548
  detail: z.ZodOptional<z.ZodString>;
528
549
  code: z.ZodLiteral<"ledger/invalid_amount">;
529
550
  status: z.ZodLiteral<400>;
551
+ }, z.core.$strip>, z.ZodObject<{
552
+ message: z.ZodString;
553
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
554
+ action: z.ZodOptional<z.ZodString>;
555
+ detail: z.ZodOptional<z.ZodString>;
556
+ code: z.ZodLiteral<"ledger/entry_not_found">;
557
+ status: z.ZodLiteral<404>;
558
+ }, z.core.$strip>, z.ZodObject<{
559
+ message: z.ZodString;
560
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
561
+ action: z.ZodOptional<z.ZodString>;
562
+ detail: z.ZodOptional<z.ZodString>;
563
+ code: z.ZodLiteral<"ledger/entry_not_reversible">;
564
+ status: z.ZodLiteral<409>;
565
+ }, z.core.$strip>, z.ZodObject<{
566
+ message: z.ZodString;
567
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
568
+ action: z.ZodOptional<z.ZodString>;
569
+ detail: z.ZodOptional<z.ZodString>;
570
+ code: z.ZodLiteral<"ledger/ref_conflict">;
571
+ status: z.ZodLiteral<409>;
530
572
  }, z.core.$strip>, z.ZodObject<{
531
573
  message: z.ZodString;
532
574
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -569,6 +611,62 @@ export declare const LogRecord: z.ZodObject<{
569
611
  detail: z.ZodOptional<z.ZodString>;
570
612
  code: z.ZodLiteral<"rating/record_forbidden">;
571
613
  status: z.ZodLiteral<403>;
614
+ }, z.core.$strip>, z.ZodObject<{
615
+ message: z.ZodString;
616
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
617
+ action: z.ZodOptional<z.ZodString>;
618
+ detail: z.ZodOptional<z.ZodString>;
619
+ code: z.ZodLiteral<"consent/unknown_purpose">;
620
+ status: z.ZodLiteral<404>;
621
+ }, z.core.$strip>, z.ZodObject<{
622
+ message: z.ZodString;
623
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
624
+ action: z.ZodOptional<z.ZodString>;
625
+ detail: z.ZodOptional<z.ZodString>;
626
+ code: z.ZodLiteral<"consent/stale_notice">;
627
+ status: z.ZodLiteral<409>;
628
+ }, z.core.$strip>, z.ZodObject<{
629
+ message: z.ZodString;
630
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
631
+ action: z.ZodOptional<z.ZodString>;
632
+ detail: z.ZodOptional<z.ZodString>;
633
+ code: z.ZodLiteral<"consent/method_below_minimum">;
634
+ status: z.ZodLiteral<400>;
635
+ }, z.core.$strip>, z.ZodObject<{
636
+ message: z.ZodString;
637
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
638
+ action: z.ZodOptional<z.ZodString>;
639
+ detail: z.ZodOptional<z.ZodString>;
640
+ code: z.ZodLiteral<"consent/withdrawal_below_grant">;
641
+ status: z.ZodLiteral<400>;
642
+ }, z.core.$strip>, z.ZodObject<{
643
+ message: z.ZodString;
644
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
645
+ action: z.ZodOptional<z.ZodString>;
646
+ detail: z.ZodOptional<z.ZodString>;
647
+ code: z.ZodLiteral<"consent/evidence_missing">;
648
+ status: z.ZodLiteral<400>;
649
+ }, z.core.$strip>, z.ZodObject<{
650
+ message: z.ZodString;
651
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
652
+ action: z.ZodOptional<z.ZodString>;
653
+ detail: z.ZodOptional<z.ZodString>;
654
+ code: z.ZodLiteral<"consent/expiry_passed">;
655
+ status: z.ZodLiteral<400>;
656
+ }, z.core.$strip>, z.ZodObject<{
657
+ message: z.ZodString;
658
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
659
+ action: z.ZodOptional<z.ZodString>;
660
+ detail: z.ZodOptional<z.ZodString>;
661
+ code: z.ZodLiteral<"consent/document_not_found">;
662
+ status: z.ZodLiteral<404>;
663
+ }, z.core.$strip>, z.ZodObject<{
664
+ message: z.ZodString;
665
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
666
+ action: z.ZodOptional<z.ZodString>;
667
+ detail: z.ZodOptional<z.ZodString>;
668
+ code: z.ZodLiteral<"consent/evidence_store_missing">;
669
+ status: z.ZodLiteral<500>;
572
670
  }, z.core.$strip>, z.ZodObject<{
573
671
  message: z.ZodString;
574
672
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/logger/record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,4GAA4G;AAC5G,eAAO,MAAM,QAAQ;;;;;EAE4F,CAAC;AAClH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAgD,CAAC;AAEtG;;;;GAIG;AACH,eAAO,MAAM,SAAS,wCAEsF,CAAC;AAC7G,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW+E,CAAC;AACtG,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMzD"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/logger/record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,4GAA4G;AAC5G,eAAO,MAAM,QAAQ;;;;;EAE4F,CAAC;AAClH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAgD,CAAC;AAEtG;;;;GAIG;AACH,eAAO,MAAM,SAAS,wCAEsF,CAAC;AAC7G,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW+E,CAAC;AACtG,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMzD"}
@@ -0,0 +1,20 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import type { ScopeKind } from "../controlPlane/scope/kind";
4
+ /**
5
+ * What an MCP tool says about itself, from the kind of thing it does. One mapping for both servers: the app's own
6
+ * tools, whose effect is a kind without `reads` or `credentials`, and the control-plane tools `pithy mcp serve`
7
+ * offers, whose route declares its scope's kind.
8
+ */
9
+ /** The MCP annotations a tool carries, set by its kind. `idempotentHint` is claimed for a read and nothing else. */
10
+ export interface ToolAnnotations {
11
+ readonly readOnlyHint: boolean;
12
+ readonly destructiveHint: boolean;
13
+ readonly idempotentHint?: true;
14
+ readonly openWorldHint: boolean;
15
+ }
16
+ /** What each kind says in a tool's description, and on the consent screen. One sentence each. */
17
+ export declare const KIND_SENTENCES: Readonly<Record<ScopeKind, string>>;
18
+ /** The MCP annotations for a kind. */
19
+ export declare function kindAnnotations(kind: ScopeKind): ToolAnnotations;
20
+ //# sourceMappingURL=annotations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"annotations.d.ts","sourceRoot":"","sources":["../../src/mcp/annotations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAE5D;;;;GAIG;AAEH,oHAAoH;AACpH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC;AAED,iGAAiG;AACjG,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAO9D,CAAC;AAEF,sCAAsC;AACtC,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CAOhE"}
@@ -0,0 +1,23 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ //#region src/mcp/annotations.ts
4
+ /** What each kind says in a tool's description, and on the consent screen. One sentence each. */
5
+ const KIND_SENTENCES = {
6
+ reads: "Reads data and changes nothing.",
7
+ writes: "Changes data in this application.",
8
+ sends: "Sends a message to somebody.",
9
+ charges: "Charges money.",
10
+ deletes: "Deletes data, and it cannot be undone.",
11
+ credentials: "Mints, rotates or revokes a credential."
12
+ };
13
+ /** The MCP annotations for a kind. */
14
+ function kindAnnotations(kind) {
15
+ return {
16
+ readOnlyHint: kind === "reads",
17
+ destructiveHint: kind === "charges" || kind === "deletes" || kind === "credentials",
18
+ ...kind === "reads" ? { idempotentHint: true } : {},
19
+ openWorldHint: kind === "sends" || kind === "charges"
20
+ };
21
+ }
22
+ //#endregion
23
+ export { KIND_SENTENCES, kindAnnotations };
@@ -0,0 +1,75 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { type ToolEffect } from "../http/routeSpec";
4
+ import type { RouteGroup } from "../openapi/document";
5
+ import { type ToolAnnotations } from "./annotations";
6
+ /**
7
+ * The app's own MCP tools, read off the composed router (`docs/AGENT-ACCESS.md` §4.1, §5).
8
+ *
9
+ * **The route declarations are already a tool list.** A route that opts in with `describeRoute({ tool })` carries
10
+ * everything a tool definition needs: the `summary` an agent chooses on, a `description` for what the schemas do not
11
+ * say, the `power` that gates it, the `scopes` a caller must carry, and an `operation` that names it. Its input is
12
+ * the route's own `validate(...)` schemas, in the same `{ path, query, body }` shape the control-plane server's tools
13
+ * take. Nothing is written twice: a route that changes its body, its power or its summary changes its tool on the
14
+ * same commit.
15
+ *
16
+ * **A tool inherits its route's power. That is the whole mapping**, and there is no tool-to-role table to maintain.
17
+ */
18
+ /** One route, as a tool. */
19
+ export interface AppTool {
20
+ /** `<capability>_<operation>`, through the control-plane server's normalizer. */
21
+ readonly name: string;
22
+ /** The capability that registered the route — the unit of consent. */
23
+ readonly capability: string;
24
+ /** The route's declared operation. */
25
+ readonly operation: string;
26
+ /** The HTTP method a call dispatches with. */
27
+ readonly method: string;
28
+ /** The mounted path a call dispatches to, Hono's spelling. */
29
+ readonly path: string;
30
+ /** The route's summary, in its capability's own words. What the consent screen lists. */
31
+ readonly summary: string;
32
+ /** What an agent reads: the summary, the route's description, and its effect said aloud. */
33
+ readonly description: string;
34
+ /** The route's input as JSON Schema. */
35
+ readonly inputSchema: Record<string, unknown>;
36
+ /** What the tool does beyond reading, or `null` for a read. */
37
+ readonly effect: ToolEffect | null;
38
+ /** The MCP annotations its effect sets. */
39
+ readonly annotations: ToolAnnotations;
40
+ /** The power the caller's role must hold, or `undefined` when the route declares none. */
41
+ readonly power: string | undefined;
42
+ /** The attestation scopes a caller must carry, from `describeRoute({ scopes })`. */
43
+ readonly scopes: readonly string[];
44
+ }
45
+ /** What each effect says in a tool's description and on the consent screen. One sentence each. */
46
+ export declare const EFFECT_SENTENCES: Readonly<Record<ToolEffect, string>>;
47
+ /** The MCP annotations for an effect. `null` is a read. */
48
+ export declare function toolAnnotations(effect: ToolEffect | null): ToolAnnotations;
49
+ /**
50
+ * Refuse a composition whose tool declarations are wrong, naming the route.
51
+ *
52
+ * **This is where "it does not compile" is enforced.** `describeRoute` cannot see the method it is mounted under, so
53
+ * a `POST` saying `tool: true` type-checks; `createBackend` calls this at assembly, so the Worker refuses to boot
54
+ * and the kit's own composition fails its tests. Five checks: a non-`GET` opting in without an effect, a `GET`
55
+ * declaring one, a tool with no operation, an operation outside the published alphabet, and two routes sharing an
56
+ * operation within a capability — or two capabilities whose names normalize to one tool.
57
+ */
58
+ export declare function assertToolDeclarations(groups: readonly RouteGroup[]): void;
59
+ /** Every tool these groups declare, in registration order. Refuses a wrong declaration first. */
60
+ export declare function appTools(groups: readonly RouteGroup[]): AppTool[];
61
+ /** What a caller holds, for {@link offeredTools}. */
62
+ export interface ToolCaller {
63
+ /** Whether the caller's role holds a power, or `null` when no organization is in force — nothing is held. */
64
+ readonly roleAllows: ((power: string) => boolean) | null;
65
+ /** The attestation scopes the caller carries. */
66
+ readonly scopes: readonly string[];
67
+ }
68
+ /** Whether this caller may call this tool, by exactly the checks its route makes. */
69
+ export declare function mayCall(tool: AppTool, caller: ToolCaller): boolean;
70
+ /**
71
+ * The tools this caller may call. **A tool a role withholds is absent, not locked**: offering it discloses that it
72
+ * exists and spends a call to learn what the answer would be (`docs/AGENT-ACCESS.md` §4.1).
73
+ */
74
+ export declare function offeredTools(tools: readonly AppTool[], caller: ToolCaller): AppTool[];
75
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+B,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,EAAmC,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEtF;;;;;;;;;;;GAWG;AAEH,4BAA4B;AAC5B,MAAM,WAAW,OAAO;IACtB,iFAAiF;IACjF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,sCAAsC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IACnC,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAKjE,CAAC;AAEF,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,eAAe,CAE1E;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAiD1E;AASD,iGAAiG;AACjG,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,OAAO,EAAE,CAuBjE;AAED,qDAAqD;AACrD,MAAM,WAAW,UAAU;IACzB,6GAA6G;IAC7G,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,qFAAqF;AACrF,wBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAGlE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,EAAE,CAErF"}
@@ -0,0 +1,118 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { ValidationError } from "../error/pithyError.js";
4
+ import { routeSpecOf } from "../http/routeSpec.js";
5
+ import { AdminOperation } from "../controlPlane/discovery/adminRoute.js";
6
+ import { isMiddlewareOnly, operationsOf } from "../openapi/operations.js";
7
+ import { inputOf } from "../controlPlane/discovery/routeInput.js";
8
+ import { controlPlaneToolName } from "../controlPlane/discovery/toolName.js";
9
+ import { KIND_SENTENCES, kindAnnotations } from "./annotations.js";
10
+ //#region src/mcp/tools.ts
11
+ /** What each effect says in a tool's description and on the consent screen. One sentence each. */
12
+ const EFFECT_SENTENCES = {
13
+ writes: KIND_SENTENCES.writes,
14
+ sends: KIND_SENTENCES.sends,
15
+ charges: KIND_SENTENCES.charges,
16
+ deletes: KIND_SENTENCES.deletes
17
+ };
18
+ /** The MCP annotations for an effect. `null` is a read. */
19
+ function toolAnnotations(effect) {
20
+ return kindAnnotations(effect ?? "reads");
21
+ }
22
+ /** Every described route in these groups, with the method it is mounted under. */
23
+ function described(groups) {
24
+ return groups.flatMap((group) => operationsOf(group.routes).filter((operation) => !isMiddlewareOnly(operation)).flatMap((operation) => {
25
+ const spec = operation.handlers.map(routeSpecOf).find((candidate) => candidate !== void 0);
26
+ return spec === void 0 ? [] : [{
27
+ capability: group.tag,
28
+ method: operation.method.toUpperCase(),
29
+ path: operation.path,
30
+ spec,
31
+ handlers: operation.handlers
32
+ }];
33
+ }));
34
+ }
35
+ function refuse(message, detail) {
36
+ throw new ValidationError({
37
+ message,
38
+ action: "Fix the route's describeRoute({ operation, tool }). A GET opts in with `tool: true`; any other method declares `tool: { effect }`.",
39
+ detail
40
+ });
41
+ }
42
+ /**
43
+ * Refuse a composition whose tool declarations are wrong, naming the route.
44
+ *
45
+ * **This is where "it does not compile" is enforced.** `describeRoute` cannot see the method it is mounted under, so
46
+ * a `POST` saying `tool: true` type-checks; `createBackend` calls this at assembly, so the Worker refuses to boot
47
+ * and the kit's own composition fails its tests. Five checks: a non-`GET` opting in without an effect, a `GET`
48
+ * declaring one, a tool with no operation, an operation outside the published alphabet, and two routes sharing an
49
+ * operation within a capability — or two capabilities whose names normalize to one tool.
50
+ */
51
+ function assertToolDeclarations(groups) {
52
+ const operations = /* @__PURE__ */ new Map();
53
+ const names = /* @__PURE__ */ new Map();
54
+ for (const route of described(groups)) {
55
+ const where = `${route.method} ${route.path}`;
56
+ const { operation, tool } = route.spec;
57
+ if (operation !== void 0) {
58
+ if (!AdminOperation.safeParse(operation).success) refuse(`The operation "${operation}" on ${where} is not a valid name.`, `capability ${route.capability} route ${where} declares operation "${operation}"; an operation is lowercase words joined by ".", "_" or "-"`);
59
+ const key = `${route.capability} ${operation}`;
60
+ const earlier = operations.get(key);
61
+ if (earlier !== void 0) refuse(`Two ${route.capability} routes declare the operation "${operation}".`, `${earlier} and ${where} both declare operation "${operation}" in capability ${route.capability}`);
62
+ operations.set(key, where);
63
+ }
64
+ if (tool === void 0) continue;
65
+ if (operation === void 0) refuse(`${where} opts in as a tool with no operation.`, `capability ${route.capability} route ${where} declares tool but no operation, so its tool has no name`);
66
+ if (route.method !== "GET" && tool === true) refuse(`${where} opts in as a tool without an effect.`, `capability ${route.capability} route ${where} is not a GET, so it must declare tool: { effect } (writes, sends, charges or deletes)`);
67
+ if (route.method === "GET" && tool !== true) refuse(`${where} is a read and declares an effect.`, `capability ${route.capability} route ${where} is a GET; a GET opts in with tool: true`);
68
+ const name = controlPlaneToolName(route.capability, operation);
69
+ const clash = names.get(name);
70
+ if (clash !== void 0) refuse(`Two routes are both the tool ${name}.`, `${clash} and ${where} both normalize to the tool name ${name}`);
71
+ names.set(name, where);
72
+ }
73
+ }
74
+ /** The description an agent reads: the summary, the route's own description, and its effect. */
75
+ function descriptionOf(spec, effect) {
76
+ return [
77
+ spec.summary,
78
+ spec.description,
79
+ effect === null ? void 0 : EFFECT_SENTENCES[effect]
80
+ ].filter((part) => part !== void 0 && part.length > 0).join(" ");
81
+ }
82
+ /** Every tool these groups declare, in registration order. Refuses a wrong declaration first. */
83
+ function appTools(groups) {
84
+ assertToolDeclarations(groups);
85
+ return described(groups).flatMap((route) => {
86
+ const { spec } = route;
87
+ if (spec.tool === void 0 || spec.operation === void 0) return [];
88
+ const effect = spec.tool === true ? null : spec.tool.effect;
89
+ return [{
90
+ name: controlPlaneToolName(route.capability, spec.operation),
91
+ capability: route.capability,
92
+ operation: spec.operation,
93
+ method: route.method,
94
+ path: route.path,
95
+ summary: spec.summary,
96
+ description: descriptionOf(spec, effect),
97
+ inputSchema: inputOf(route.handlers),
98
+ effect,
99
+ annotations: toolAnnotations(effect),
100
+ power: spec.power,
101
+ scopes: spec.scopes ?? []
102
+ }];
103
+ });
104
+ }
105
+ /** Whether this caller may call this tool, by exactly the checks its route makes. */
106
+ function mayCall(tool, caller) {
107
+ if (tool.power !== void 0 && (caller.roleAllows === null || !caller.roleAllows(tool.power))) return false;
108
+ return tool.scopes.every((scope) => caller.scopes.includes(scope));
109
+ }
110
+ /**
111
+ * The tools this caller may call. **A tool a role withholds is absent, not locked**: offering it discloses that it
112
+ * exists and spends a call to learn what the answer would be (`docs/AGENT-ACCESS.md` §4.1).
113
+ */
114
+ function offeredTools(tools, caller) {
115
+ return tools.filter((tool) => mayCall(tool, caller));
116
+ }
117
+ //#endregion
118
+ export { EFFECT_SENTENCES, appTools, assertToolDeclarations, mayCall, offeredTools, toolAnnotations };
@@ -1 +1 @@
1
- {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/openapi/document.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/openapi/document.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
- import { CONTROL_PLANE_HEADER } from "../controlPlane/wire.js";
3
+ import { ErrorBody } from "../error/wire.js";
4
4
  import { routeSpecOf } from "../http/routeSpec.js";
5
5
  import { requestContractOf } from "../http/validation.js";
6
- import { ErrorBody } from "../error/wire.js";
6
+ import { CONTROL_PLANE_HEADER } from "../controlPlane/wire.js";
7
7
  import { pathParams } from "../http/routeContract.js";
8
+ import { isMiddlewareOnly, operationsOf } from "./operations.js";
8
9
  import { z } from "zod";
9
10
  //#region src/openapi/document.ts
10
11
  /**
@@ -29,7 +30,7 @@ const SECURITY_SCHEMES = {
29
30
  bearer: {
30
31
  type: "http",
31
32
  scheme: "bearer",
32
- description: "A short-lived access token from `@pithy-sh/auth`, sent as `Authorization: Bearer <token>`."
33
+ description: "A session token from `@pithy-sh/auth`, sent as `Authorization: Bearer <token>`: the one sign-in returns, then the `refreshToken` each `/token/rotate` answers with. The rotation's `accessToken` is a JWT for services outside the Worker, and these routes refuse it."
33
34
  },
34
35
  session: {
35
36
  type: "apiKey",
@@ -76,28 +77,6 @@ function jsonSchema(schema, io) {
76
77
  });
77
78
  return rest;
78
79
  }
79
- function operationsOf(routes) {
80
- const byKey = /* @__PURE__ */ new Map();
81
- for (const route of routes) {
82
- const key = `${route.method} ${route.path}`;
83
- const entry = byKey.get(key) ?? {
84
- method: route.method,
85
- path: route.path,
86
- handlers: []
87
- };
88
- entry.handlers.push(route.handler);
89
- byKey.set(key, entry);
90
- }
91
- return [...byKey.values()];
92
- }
93
- /**
94
- * An `ALL` entry with no spec is `app.use` — middleware, not a route — because Hono records both as
95
- * `ALL`. An `app.all` route that forgot its `describeRoute` is therefore invisible to the coverage
96
- * check, which is the one blind spot here; the kit has one such route and it is described.
97
- */
98
- function isMiddlewareOnly(operation) {
99
- return operation.method === "ALL" && !operation.handlers.some((handler) => routeSpecOf(handler));
100
- }
101
80
  /** Every route in these groups that registered no `describeRoute`. Empty is the contract being met. */
102
81
  function undescribedRoutes(groups) {
103
82
  return groups.flatMap((group) => operationsOf(group.routes).filter((operation) => !isMiddlewareOnly(operation)).filter((operation) => !operation.handlers.some((handler) => routeSpecOf(handler))).map(({ method, path }) => ({
@@ -204,7 +183,10 @@ function operationOf(tag, method, operation, spec) {
204
183
  security,
205
184
  "x-pithy-verification": strategies
206
185
  },
207
- ...spec.scopes === void 0 || spec.scopes.length === 0 ? {} : { "x-pithy-scopes": spec.scopes }
186
+ ...spec.scopes === void 0 || spec.scopes.length === 0 ? {} : { "x-pithy-scopes": spec.scopes },
187
+ ...spec.power === void 0 ? {} : { "x-pithy-power": spec.power },
188
+ ...spec.operation === void 0 ? {} : { "x-pithy-operation": spec.operation },
189
+ ...spec.tool === void 0 ? {} : { "x-pithy-tool": spec.tool === true ? { effect: null } : spec.tool }
208
190
  };
209
191
  }
210
192
  /** The methods an operation is documented under: its own, or for `app.all` the ones its spec names. */
@@ -0,0 +1,35 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { type RouteSpec } from "../http/routeSpec";
4
+ import type { RouteGroup, RouterRoute } from "./document";
5
+ /**
6
+ * The composed route table as operations: one per method and path, with the spec its `describeRoute` declared.
7
+ *
8
+ * Hono keeps one entry per handler, so a route with a `describeRoute` ahead of its handler appears twice in
9
+ * `app.routes`. Two readers need the grouped view: the OpenAPI document, which turns each operation into a path
10
+ * item, and the evidence pack (#821), which counts how every route verifies its caller. They group the same way
11
+ * because they group here, and the pack never loads the JSON Schema conversion the document needs.
12
+ */
13
+ /** One route's handlers, grouped by method and path the way Hono stores them: one entry per handler. */
14
+ export interface Operation {
15
+ readonly method: string;
16
+ readonly path: string;
17
+ readonly handlers: unknown[];
18
+ }
19
+ /** Group a route table into operations, in registration order. */
20
+ export declare function operationsOf(routes: readonly RouterRoute[]): Operation[];
21
+ /**
22
+ * An `ALL` entry with no spec is `app.use` — middleware, not a route — because Hono records both as
23
+ * `ALL`. An `app.all` route that forgot its `describeRoute` is therefore invisible to the coverage
24
+ * check, which is the one blind spot here; the kit has one such route and it is described.
25
+ */
26
+ export declare function isMiddlewareOnly(operation: Operation): boolean;
27
+ /** One route, and the spec it declared — `undefined` for a route that registered no `describeRoute`. */
28
+ export interface DescribedOperation {
29
+ readonly method: string;
30
+ readonly path: string;
31
+ readonly spec: RouteSpec | undefined;
32
+ }
33
+ /** Every route in these groups, middleware left out, each with the spec it declared or `undefined`. */
34
+ export declare function describedOperations(groups: readonly RouteGroup[]): DescribedOperation[];
35
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/openapi/operations.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;GAOG;AAEH,wGAAwG;AACxG,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;CAC9B;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,SAAS,EAAE,CASxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAE9D;AAED,wGAAwG;AACxG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;CACtC;AAED,uGAAuG;AACvG,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,kBAAkB,EAAE,CAUvF"}
@@ -0,0 +1,37 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { routeSpecOf } from "../http/routeSpec.js";
4
+ //#region src/openapi/operations.ts
5
+ /** Group a route table into operations, in registration order. */
6
+ function operationsOf(routes) {
7
+ const byKey = /* @__PURE__ */ new Map();
8
+ for (const route of routes) {
9
+ const key = `${route.method} ${route.path}`;
10
+ const entry = byKey.get(key) ?? {
11
+ method: route.method,
12
+ path: route.path,
13
+ handlers: []
14
+ };
15
+ entry.handlers.push(route.handler);
16
+ byKey.set(key, entry);
17
+ }
18
+ return [...byKey.values()];
19
+ }
20
+ /**
21
+ * An `ALL` entry with no spec is `app.use` — middleware, not a route — because Hono records both as
22
+ * `ALL`. An `app.all` route that forgot its `describeRoute` is therefore invisible to the coverage
23
+ * check, which is the one blind spot here; the kit has one such route and it is described.
24
+ */
25
+ function isMiddlewareOnly(operation) {
26
+ return operation.method === "ALL" && !operation.handlers.some((handler) => routeSpecOf(handler));
27
+ }
28
+ /** Every route in these groups, middleware left out, each with the spec it declared or `undefined`. */
29
+ function describedOperations(groups) {
30
+ return groups.flatMap((group) => operationsOf(group.routes).filter((operation) => !isMiddlewareOnly(operation)).map((operation) => ({
31
+ method: operation.method,
32
+ path: operation.path,
33
+ spec: operation.handlers.map(routeSpecOf).find((candidate) => candidate !== void 0)
34
+ })));
35
+ }
36
+ //#endregion
37
+ export { describedOperations, isMiddlewareOnly, operationsOf };
@@ -0,0 +1,11 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import type { SocketChannel } from "../http/socket";
4
+ import { type PresenceDeclaration } from "./declaration";
5
+ /**
6
+ * A capability's presence room socket, declared for the AsyncAPI contract. `defineCapability` adds it to the
7
+ * capability's `sockets` whenever it declares room kinds, from the same `basePath` the routes mount on, so a
8
+ * declared socket and a mounted one cannot be two different things.
9
+ */
10
+ export declare function presenceRoomsSocket(capability: string, presence: PresenceDeclaration): SocketChannel;
11
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/presence/channel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,KAAK,mBAAmB,EAAsB,MAAM,eAAe,CAAC;AAc7E;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,GAAG,aAAa,CAsBpG"}
@@ -0,0 +1,65 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { PRESENCE_ROOM_VERSIONS, PresenceActivityFrame, PresenceJoinedFrame, PresenceLeftFrame, PresenceRoomErrorFrame, PresenceRoomInitFrame, PresenceRoomPing, PresenceRoomPong, PresenceSetActivityFrame } from "./frames.js";
4
+ import { presenceSocketPath } from "./declaration.js";
5
+ import { PresenceRoomParams } from "./http/schemas.js";
6
+ //#region src/presence/channel.ts
7
+ /**
8
+ * A capability's presence room socket, declared for the AsyncAPI contract. `defineCapability` adds it to the
9
+ * capability's `sockets` whenever it declares room kinds, from the same `basePath` the routes mount on, so a
10
+ * declared socket and a mounted one cannot be two different things.
11
+ */
12
+ function presenceRoomsSocket(capability, presence) {
13
+ return {
14
+ name: `${capability}PresenceRooms`,
15
+ path: presenceSocketPath(presence.basePath),
16
+ summary: `Who else has a ${capability} record open, and what they are doing, live.`,
17
+ description: `Mint a ticket first — \`POST /control-plane/presence/tickets\` for a management client, \`POST ${presence.basePath}/presence/tickets\` for a signed-in user — then offer \`pithy.presence.v1\` and \`pithy.ticket.<ticket>\` in \`Sec-WebSocket-Protocol\`. The ticket is the credential: single use, 60 seconds, this room only. The room sends \`init\` first, then \`joined\`, \`left\` and \`activity\` as they happen. Send \`set_activity\` to announce one of the kind's declared activities, and \`ping\` as plain text to get \`pong\`. Room kinds: ${presence.rooms.map((room) => `\`${room.kind}\``).join(", ")}.`,
18
+ verification: "public",
19
+ params: PresenceRoomParams,
20
+ versions: PRESENCE_ROOM_VERSIONS,
21
+ send: [
22
+ {
23
+ name: "init",
24
+ summary: "Everyone in the room, sent once on connect.",
25
+ schema: PresenceRoomInitFrame
26
+ },
27
+ {
28
+ name: "joined",
29
+ summary: "Another participant joined.",
30
+ schema: PresenceJoinedFrame
31
+ },
32
+ {
33
+ name: "left",
34
+ summary: "Another participant left, or their socket dropped.",
35
+ schema: PresenceLeftFrame
36
+ },
37
+ {
38
+ name: "activity",
39
+ summary: "Another participant changed what they are doing.",
40
+ schema: PresenceActivityFrame
41
+ },
42
+ {
43
+ name: "error",
44
+ summary: "A frame the room could not accept.",
45
+ schema: PresenceRoomErrorFrame
46
+ },
47
+ {
48
+ name: "pong",
49
+ summary: "The answer to `ping`, as plain text.",
50
+ text: PresenceRoomPong.value
51
+ }
52
+ ],
53
+ receive: [{
54
+ name: "set_activity",
55
+ summary: "Announce a declared activity.",
56
+ schema: PresenceSetActivityFrame
57
+ }, {
58
+ name: "ping",
59
+ summary: "The keepalive, as plain text.",
60
+ text: PresenceRoomPing.value
61
+ }]
62
+ };
63
+ }
64
+ //#endregion
65
+ export { presenceRoomsSocket };