@wildo-ai/saas-backend-lib 1.1.12 → 1.1.13

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 (226) hide show
  1. package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
  2. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
  3. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
  4. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
  5. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
  6. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
  7. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
  8. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
  9. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
  10. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +10 -1
  11. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
  12. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
  13. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
  14. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +25 -1
  15. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
  16. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
  17. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.map +1 -1
  18. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js +68 -5
  19. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
  20. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
  21. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  22. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +6 -3
  23. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  24. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +83 -0
  25. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  26. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +217 -14
  27. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  28. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
  29. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
  30. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
  31. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
  32. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
  33. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
  34. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
  35. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
  36. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
  37. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
  38. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
  39. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
  40. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
  41. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
  42. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
  43. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
  44. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
  45. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
  46. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
  47. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
  48. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
  49. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
  50. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
  51. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
  52. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
  53. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
  54. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
  55. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
  56. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
  57. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
  58. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
  59. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
  60. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
  61. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
  62. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
  63. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
  64. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
  65. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
  66. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
  67. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
  68. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
  69. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
  70. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
  71. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
  72. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
  73. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
  74. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
  75. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
  76. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
  77. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
  78. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
  79. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
  80. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
  81. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
  82. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
  83. package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
  84. package/dist/esm/external-providers/services/content-safety.backend.service.js.map +1 -1
  85. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  86. package/dist/esm/external-providers/services/embeddings.backend.service.js +2 -0
  87. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  88. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -0
  89. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  90. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +23 -0
  91. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  92. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
  93. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
  94. package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
  95. package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
  96. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
  97. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
  98. package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
  99. package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
  100. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
  101. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
  102. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
  103. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
  104. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
  105. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
  106. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
  107. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
  108. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
  109. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  110. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +37 -0
  111. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  112. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
  113. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
  114. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
  115. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
  116. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
  117. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  118. package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
  119. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  120. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
  121. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
  122. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
  123. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
  124. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  125. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +132 -22
  126. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  127. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
  128. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
  129. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
  130. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
  131. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  132. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +18 -2
  133. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  134. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
  135. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  136. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +58 -0
  137. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  138. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
  139. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
  140. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
  141. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
  142. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
  143. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
  144. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
  145. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
  146. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
  147. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
  148. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
  149. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
  150. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
  151. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
  152. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
  153. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
  154. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
  155. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
  156. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
  157. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
  158. package/dist/esm/index.d.ts +1 -0
  159. package/dist/esm/index.d.ts.map +1 -1
  160. package/dist/esm/index.js +1 -0
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/inject/models/container.d.ts.map +1 -1
  163. package/dist/esm/inject/models/container.js +6 -0
  164. package/dist/esm/inject/models/container.js.map +1 -1
  165. package/dist/esm/inject/models/service-types.d.ts +5 -0
  166. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  167. package/dist/esm/inject/models/service-types.js +3 -0
  168. package/dist/esm/inject/models/service-types.js.map +1 -1
  169. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
  170. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  171. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  172. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
  173. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  174. package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
  175. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  176. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -1
  177. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  178. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +15 -4
  179. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  180. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
  181. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js +3 -1
  182. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
  183. package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -1
  184. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  185. package/dist/esm/runtime/services/http-server.backend.service.js +11 -3
  186. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  187. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
  188. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
  189. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
  190. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
  191. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
  192. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
  193. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +87 -15
  194. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -1
  195. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
  196. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
  197. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -1
  198. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
  199. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +65 -24
  200. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
  201. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -1
  202. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  203. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +84 -2
  204. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  205. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
  206. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  207. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +13 -5
  208. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  209. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
  210. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
  211. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
  212. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
  213. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
  214. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
  215. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js.map +1 -1
  216. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
  217. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js +11 -4
  218. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
  219. package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
  220. package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
  221. package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
  222. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
  223. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
  224. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
  225. package/dist/tsconfig.build.tsbuildinfo +1 -1
  226. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"function-tools.backend.definitions.js","sourceRoot":"","sources":["../../../../src/flows-actors/models/function-tools.backend.definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n type FlowsActors_PersonalDataModelTreatment,\n type FlowsActors_OutputModerationPolicy,\n CoreResourceOperation,\n ErrorType,\n RedactionType,\n ResourceOperationVariantType,\n ResourcesConfig_OperationPathUtils,\n isWildoBackendError,\n type ResourceType,\n type ResourceConfiguration_Operation,\n type ResourceConfiguration_OperationPath,\n ResourceOperationIdempotencyKeyRequirement,\n IDEMPOTENCY_KEY_MAX_LENGTH,\n IDEMPOTENCY_KEY_TOOL_ARGUMENT,\n type ResourceOperationRiskLevel,\n HumanDecision_RouteKind,\n FunctionToolAuthorityKind,\n type FunctionToolAuthorityDeclaration,\n AutonomousTurnTrigger,\n FlowsActors_InitiationKind,\n ReviewEscalationActionKind,\n reviewDeadlinesDeclarationIssues,\n type ReviewDeadlineStage,\n type ReviewDeadlinesDeclaration,\n type HumanDecision_AnswerChannels,\n type HumanDecision_StepUpRequirement,\n humanDecisionAnswerChannelsIssues,\n humanDecisionStepUpDeclarationIssues,\n humanDecisionStepUpRequirementOf,\n conversationalActorOf,\n type ActorSystem,\n AskPerson_ToolInputSchema,\n PresentRecords_ToolInputSchema,\n Resources_Filter_NumberRangeSchema,\n isResourcesFilterNumberRangeSchema,\n Resources_Filter_YearMonthRangeSchema,\n isResourcesFilterYearMonthRangeSchema,\n type PresentRecords_ToolInput,\n type PresentRecords_ToolResult,\n flowsActorsToolLabelKey,\n type FlowsActorsToolLabelSlot,\n RagRetrievalEmbeddingStatus,\n RagRetrievalSearchStatus,\n OperationDispatchPlane,\n ResourcePrimaryScope,\n ResourcesConfigOperationsDtosBuilderUtils,\n jsonParsingSchemaOf,\n} from '@wildo-ai/saas-models';\nimport { ElectronicSignature_Level } from '@wildo-ai/external-connectors-models';\nimport { takeIdempotencyKeyToolArgument } from '~wildo-backend-lib/base-classes/services/controllers/utils/idempotency-key-tool-argument.backend.utils';\n\nimport { toResponseSafeToolOutput } from '~wildo-backend-lib/base-classes/services/controllers/utils/operation-response-serializer.backend.utils';\nimport { declaredPolicySubjectKey, resolveDeclaredPolicySubject } from '~wildo-backend-lib/security/authentications/services/utils/external-turn-rate-limit.backend.utils';\nimport {\n OPERATION_DISPATCH_PLANE_FACTS,\n declaredRateLimitScopeKey,\n recordOperationRateLimitRefusal,\n} from '~wildo-backend-lib/errors/utils/declared-rate-limit-refusal.backend.utils';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { AuthorizationsBackendService } from '~wildo-backend-lib/security/authorizations/services/authorizations.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport { toPortableModelToolName } from '~wildo-backend-lib/flows-actors/models/model-tool-name.backend.utils';\nimport type { RateLimitBackendService } from '~wildo-backend-lib/errors/services/rate-limit.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type { SocketAuthResult } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { RagRetrievalBackendService, RagRetrievalResult } from '~wildo-backend-lib/rag/services/rag-retrieval.backend.service';\nimport { observeDispatchedRecordOwners } from '~wildo-backend-lib/flows-actors/content-guardrails/tool-call-record-owners.backend';\nimport { argumentsCarryingWithheldMarkers, placeholderTolerantInputSchema, PersonalDataPlaceholderRefusal, type PersonalDataGuard, type PersonalDataPlaceholderTable, type PersonalFieldMap } from '~wildo-backend-lib/flows-actors/content-guardrails/personal-data-guard.backend.utils';\n\n/**\n * Function-Tool Contract (backend)\n * ================================\n *\n * An executable tool an AI agent can call during an invocation (the runtime\n * behind an agent's declarative `capabilities.tools.functionRefs`). Unlike the\n * shared agent/system schemas, a `FunctionTool` carries backend execution logic,\n * so it lives in `saas-backend-lib`, not `saas-models`.\n *\n * Tools are registered per-application through\n * `BackendDomainModule.flowsActors.functionTools`, indexed by `functionRef` in\n * the `FlowsActorsRegistryService`, and resolved + wired into the AI-SDK `tools`\n * parameter by `AgentsBackendService` when a streaming invocation runs. The\n * engine supplies the execution *context* (caller identity + backend services)\n * at call time; the tool itself stays a pure, reusable declaration.\n */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.tool-dispatch-obligations facet:layer:backend facet:audience:app-developer\n *\n * Backend services a tool may use at execution time (supplied by the caller).\n *\n * ⚠️ **If your tool DISPATCHES a resource operation, call `dispatchResourceOperationAsTool` — do not\n * reach for these services yourself.**\n *\n * A tool enters at the SERVICE tier, bypassing Express, so two gates that live on the HTTP\n * controller never run for it: the operation's declared `roles` ACL and its authored `rateLimit?`.\n * `dispatchResourceOperationAsTool` resolves the operation, builds the scoped execution context,\n * applies both gates in the right order and dispatches — one exported call, and the same one\n * `resourceReadTool` and `resourceWriteTool` use.\n *\n * ```ts\n * const rows = await dispatchResourceOperationAsTool({\n * ctx, resourceType: 'todos', operationIdentifier: CoreResourceOperation.LIST,\n * data: { filter: undefined, page: 1, limit: 20 }, options: { paginated: true },\n * });\n * ```\n *\n * **This prose used to name two calls a hand-written tool owed, and both were module-private (#556)\n * — so an author who read it and agreed could not discharge the obligation.** Naming ONE importable\n * call replaces that: the correct path is now also the shortest, which is the only mechanism that\n * survives an author who has not read this paragraph.\n *\n * Skipping the gates means a caller whose roles the operation REFUSES, but whose tenancy admits the\n * row, succeeds — the operation's `accessControl` simply unenforced on this plane. It is quiet:\n * tenancy still applies, so the tool returns the caller's own tenant's rows and LOOKS like it works.\n * That is right for a framework-internal caller and wrong here, where the caller is an external\n * principal naming an operation on their own authority.\n *\n * The services below remain on this interface because the seam is built from them, and because a\n * tool that dispatches NOTHING — a calculator, a formatter, a unit converter — is a legitimate shape\n * that needs neither gate.\n *\n * What you still get for free, on every tool: the repository's contextual filter in full — tenancy,\n * relationship narrowing, organization-unit narrowing, the anonymous guard and the retention hide,\n * all fail-closed — plus the whole operation pipeline of validation, enabled conditions, custom\n * implementation and hooks.\n */\nexport interface FunctionToolExecutionServices {\n resourcesRegistry: ResourcesRegistryBackendService;\n servicesRegistryHandler: ServicesRegistryHandlerBackendService;\n executionContextCreator: ExecutionContextCreatorBackendService;\n /**\n * Enforces an operation's OWN authored `rateLimit?` policy on this plane.\n *\n * Present because a tool DISPATCHES A RESOURCE OPERATION while bypassing Express, so the\n * HTTP route's counts of the declared policy never run. A\n * hand-written {@link FunctionTool} should dispatch through {@link dispatchResourceOperationAsTool},\n * which charges this service, applies the roles ACL and records a refusal (#3008). Calling\n * `checkPolicyForSubject(...)` on THIS service directly is the fallback for a tool that does not\n * dispatch through the seam: it charges the policy and records NO refusal. (The factories below wrap\n * it in the module-private `assertDeclaredOperationRateLimit`, which is not importable.)\n */\n rateLimitService: RateLimitBackendService;\n /**\n * Applies the dispatched operation's own declared `roles` ACL.\n *\n * Present because a tool enters at the SERVICE tier, and **the role gate is a CONTROLLER-tier\n * gate** — `ServicesRegistryHandlerBackendService`'s verbs apply the repository's contextual\n * filter and the whole operation pipeline, and deliberately apply no role check, because their\n * dominant population is the authentication reads that run before a role-bearing principal\n * exists. That is right for a framework-internal caller and wrong for this plane, whose caller is\n * an external principal (an A2A agent, or a user's own WebSocket) naming an operation on their\n * own authority. Without this the operation's `accessControl` was simply unenforced here: a\n * caller whose roles the operation refuses, but whose tenancy admits the row, succeeded.\n *\n * A hand-written {@link FunctionTool} that dispatches a resource operation owes the same call —\n * `authorizeInController(idOrIds, executionContext)` on THIS service. (The factories below wrap it\n * in the module-private `authorizeToolDispatch`, which is not importable from outside this file.)\n */\n authorizer: AuthorizationsBackendService;\n /**\n * Records the first refusal of each window of an operation's declared `rateLimit?` (#3008): one\n * `OPERATION_RATE_LIMIT_REFUSED` row naming the plane (an agent tool or a chat command), the operation, the subject\n * counted and the window. Optional and feature-detected: without it the policy still refuses, unrecorded. A\n * hand-written {@link FunctionTool} that dispatches through {@link dispatchResourceOperationAsTool} is charged and\n * recorded by it; one that calls `checkPolicyForSubject(...)` on its own is charged and NOT recorded.\n */\n auditLogs?: Pick<AuditLogsBackendService, 'logOperationRateLimitRefused'>;\n /**\n * Searches the application's retrieval index on the caller's own authority (#2300), for {@link retrievalTool}.\n * Optional: a plane that offers no retrieval leaves it out, and the retrieval tool then refuses with a sentence\n * rather than answering with nothing. A tool you write yourself may call it too: pass the execution context you\n * built from the caller's auth, never one with more authority.\n */\n ragRetrieval?: Pick<RagRetrievalBackendService, 'retrieve'>;\n}\n/** @wildo_source:part:end saas.backend.flows-actors.tool-dispatch-obligations */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.function-tool facet:layer:backend facet:family:flows-actors\n *\n * Execution context threaded into every tool call. Carries the CALLER's verified\n * identity (`auth`) so a tool reads/writes as the user with the user's own\n * visibility — never trusting LLM-supplied identity — plus the backend services\n * the tool may use. The engine supplies this at call time; a tool never fabricates\n * identity from the model's arguments.\n *\n * assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — a tool acts on its caller's server-verified authority, which the model can never supply.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n */\nexport interface FunctionToolExecutionContext {\n /** The authenticated caller (server-verified identity + roles). */\n auth: SocketAuthResult;\n /** Active organization scope for the call, when applicable. */\n organizationId?: string;\n /**\n * The conversational execution (the thread) this call is a turn of, when the tool runs inside\n * one. A tool that starts work elsewhere — a run, a task — stamps it onto that work so the thread\n * can list what it started; the engine supplies it and reads nothing back from it.\n */\n executionId?: string;\n /**\n * The actors system the execution runs in, when the tool runs inside one. Supplied by the engine;\n * like `executionId`, it is recorded on the agent frame the call runs in, so every audit row the tool\n * causes names the agent, the execution and the system without the tool doing anything.\n */\n systemRef?: string;\n /** Backend services the tool may use. */\n services: FunctionToolExecutionServices;\n /**\n * The human decision this call runs under, when a resumed turn is carrying out an approval (#1594).\n * The agent frame copies it onto `agentActor.decisionRef`, so the write the approved tool makes names\n * the decision that authorized it. Absent on every call no one had to approve.\n */\n decisionRef?: string;\n /**\n * #2904: the id of the approval seal of the answer `decisionRef` names (an `approvalSeals` row), set by the engine from\n * the release that wrote it, never from the model or a request. A tool that RECORDS the decision (a sign-off, an\n * acceptance) stores it beside the decider, so the record points at the signed evidence of what the person was shown\n * and answered. Absent when the answer was not sealed: a decision answered before seals existed, or a host that binds\n * no seal services. Its absence never changes whether the call may run.\n */\n decisionSealId?: string;\n /**\n * Which door opened the turn this call belongs to (#1594), read by the engine from the execution ROW —\n * at turn start and again at a decision's resume — never from the caller. It decides whether a gated call\n * may pause for a person or must be denied (`admitsDecisionSuspension`). Tools do not need to read it.\n */\n initiationKind?: FlowsActors_InitiationKind | null;\n /**\n * AUTONOMOUS turns only (#1611): what started the turn, read from the row. An `INBOUND_DELIVERY` turn\n * runs on content from outside, so the engine offers it only tools that READ or that are gated on a\n * reviewer — see {@link FunctionTool.effect}.\n */\n autonomousTrigger?: AutonomousTurnTrigger;\n /**\n * #2292: this conversation's personal-data placeholders, when its agent declares `contentGuardrails.personalData` with\n * `TOKENIZE`. Loaded by the engine from the conversation and stored again with the turn; a tool never needs it.\n */\n personalDataPlaceholders?: PersonalDataPlaceholderTable;\n /**\n * #3295: on a resumed turn, the personal-data treatment the turn paused under. The paused messages are in the form it\n * wrote, placeholders included, and only a guard under it can read them back, so the resume runs under at least this\n * however the agent's declaration or an organization's policy has moved since. Its own field rather than an entry of the\n * turn's policy frame: a frame applies only to the organizations it covers, and a call can name none, or another.\n */\n heldPersonalDataTreatment?: FlowsActors_PersonalDataModelTreatment;\n /**\n * #3364 step 3: on a resumed turn, the output moderation its replies were judged under when it paused, tightened by the\n * organizations whose records it had read. Those records stay in the paused messages, so the resume is judged under at\n * least this (`OutputModerationGuard.tighten`).\n */\n heldOutputModeration?: FlowsActors_OutputModerationPolicy;\n /**\n * #3313: told a function tool's `execute` is about to run, with the id of its call, once its arguments are final. The one\n * point that means the call ran: the SDK reports an approved call it refused to run as a `tool-error`, so an error event\n * says nothing about whether `execute` was reached. A resumed turn reads this to tell an accepted call that ran and failed\n * from one that never ran.\n */\n onFunctionToolExecuting?: (toolCallId: string) => void;\n}\n\n/**\n * What a tool can do to the world, as its author DECLARES it (#1611). Read by the engine to decide which\n * tools an agent is offered when the turn's input is untrusted — an autonomous turn started by an inbound\n * delivery, whose content came from outside and must never steer a write nobody reviews.\n */\nexport enum FunctionToolEffect {\n /** The tool only reads. Offered to every turn. */\n READ = 'read',\n /**\n * The tool may change something — a record, a message sent, money moved. The meaning of an ABSENT\n * declaration too: an unclassified tool is treated as a write, so forgetting to declare it withholds the\n * tool from untrusted turns rather than exposing it.\n */\n WRITE = 'write',\n}\n\n/**\n * A single agent-callable tool (grounding / action an agent can invoke).\n *\n * Register instances on a backend module's `flowsActors.functionTools`; reference\n * one from an agent's `capabilities.tools.functionRefs` by its `functionRef`. The\n * engine resolves each declared ref into an AI-SDK tool at invocation time and\n * calls `execute(args, context)` with the caller's {@link FunctionToolExecutionContext}\n * (so the tool acts as the user, with the user's own visibility). For reading a\n * resource, prefer the `resourceReadTool(resourceType)` factory over a hand-written\n * tool. Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // a custom tool\n * const echoTool: FunctionTool = {\n * functionRef: 'demo.echo',\n * description: 'Echo the provided text back.',\n * inputSchema: z.object({ text: z.string() }),\n * effect: FunctionToolEffect.READ,\n * // A hand-written tool says how it reaches data (#2839): this one reaches none.\n * authority: { kind: FunctionToolAuthorityKind.NO_APPLICATION_DATA, reason: 'It returns its own argument.' },\n * execute: async (args) => ({ echoed: args.text }),\n * };\n */\nexport interface FunctionTool {\n /** Stable id referenced from `agent.capabilities.tools.functionRefs`. */\n functionRef: string;\n /**\n * Natural-language description shown to the model (what the tool does + when).\n *\n * It is also the intent the labelling pipeline words the tool from for a PERSON (#2551): the title of the call's card\n * in the conversation and its working line, `flows_actors_tools.<model tool name>.{title,working}`, generated by\n * `wildo generate labels`. So say what the tool does for the person, not only how the model should call it.\n */\n description: string;\n /** Zod schema of the tool's arguments (surfaced to the model). */\n inputSchema: z.ZodTypeAny;\n /**\n * The tool's arguments as the application's RESOURCES declare them. Called ONCE, when the tool is registered (both\n * hosts register resources first; a host that does not keeps the authored schema, with a warning); what it answers\n * REPLACES `inputSchema` and `description` for every reader — the\n * model, an approval card, an approval's validation — so all of them read one schema. For a tool whose arguments ARE a\n * resource's declaration: {@link resourceReadTool} offers the filters its resource's search declares. Answering\n * `undefined` keeps the authored schema and description.\n */\n bindToResources?: (resources: FunctionToolResourceDeclarations) => Pick<FunctionTool, 'inputSchema' | 'description'> | undefined;\n /** Execute the tool with validated args under the caller's context. */\n execute: (args: any, context: FunctionToolExecutionContext) => Promise<unknown>;\n /**\n * Require a HUMAN decision before this tool runs (human-in-the-loop).\n *\n * When set, a turn that reaches this tool SUSPENDS instead of executing it: the run state is\n * persisted, the execution moves to `AWAITING_APPROVAL`, and the caller is asked to approve or\n * deny. Approving resumes the turn and runs the tool; denying resumes it and tells the model the\n * call was refused, so the agent can respond rather than silently stalling.\n *\n * Declare it on tools whose effect a person should authorise — sending money, emailing a\n * customer, deleting at scale — not on reads.\n *\n * ⚠️ Two things worth knowing before you set this:\n *\n * 1. **It requires a configured approval secret.** Approval decisions are HMAC-signed so a client\n * cannot forge one. A turn that would expose an approval-gated tool with no secret configured\n * REFUSES TO RUN rather than falling back to unsigned approvals — the tools someone bothered to\n * gate are exactly the ones where a forged approval matters most.\n * 2. **This is Wildo's declaration, not the model SDK's.** The engine translates it into the\n * SDK's call-level approval configuration. Do not reach for the SDK's own tool-level\n * `needsApproval`: it is deprecated, and approval is handled at the call level now.\n *\n * `true` means the person whose turn it is answers (an OWNER route). To route the decision to a\n * reviewer instead, declare {@link FunctionTool.humanApproval}; when both are set, `humanApproval` wins.\n */\n requiresHumanApproval?: boolean;\n /**\n * WHO must approve this tool call before it runs (#1594). Declaring it gates the tool exactly as\n * `requiresHumanApproval` does, and routes the decision:\n *\n * - `OWNER` — the person whose turn it is (what `requiresHumanApproval: true` means);\n * - `ROLE` — anyone holding `eligibleRole` in the organization the work belongs to, EXCEPT the person\n * whose turn raised it. Any holder may claim it for themselves;\n * - `ASSIGNEE` — the one person `assignee` resolves, who must hold `eligibleRole`.\n *\n * Whoever answers only decides WHETHER the call runs. It always runs under the authority of the\n * person (or machine) whose turn raised it, re-checked when the answer arrives — a reviewer's\n * wider rights never reach the agent.\n *\n * A malformed declaration (a ROLE route with no role, an ASSIGNEE route with no resolver) stops the\n * application at startup: a gate nobody can answer is refused before it can strand a turn.\n */\n humanApproval?: FunctionTool_HumanApprovalGate;\n /**\n * What this tool can do, as you declare it (#1611). `READ` tools are offered to every turn, including an\n * autonomous turn started by an inbound delivery. Anything else — `WRITE`, or no declaration at all — is\n * offered to such a turn only when it is gated on a REVIEWER (`humanApproval` with a ROLE or ASSIGNEE\n * route), because the delivery's content came from outside and must not steer a write nobody reviews.\n * `resourceReadTool` declares `READ` and `resourceWriteTool` declares `WRITE` for you; declare it on a\n * tool you write by hand.\n */\n effect?: FunctionToolEffect;\n /**\n * The resource whose fields this tool's arguments are (#1923). When a decider's decision on a call is exported as\n * evaluation data, an argument is an identifier if the tool's `inputSchema` OR this resource's own schema declares it\n * one (`.isForeignKey()`, `.isPrimaryKey()`, `IDENTITY` / `CONTACT_DETAILS` data), so a tool whose argument schema\n * restates a resource field without its decorators still has the field's meaning. `rowIdArgument` names the\n * argument that addresses the row (the row's own id). `resourceWriteTool` declares both for you.\n *\n * It also decides who sees a gated call's decision (#2734). The card shows the call's arguments, so a representative\n * (someone working in the organization through an organization relationship) is shown and may answer it only when\n * their relationship may read the row `rowIdArgument` names. Without a declared row, the decision goes to the\n * organization's own staff and to representatives of the requester's own relationship only. An edit from someone\n * answering only through a relationship may not point the row at a record their relationship cannot read, nor turn the\n * row argument into something that names no record, nor change an argument that is, or contains at any depth, a field\n * declared `.isForeignKey()` on the tool's argument schema or on any schema of this resource; and an edit the engine\n * cannot judge (this resource can no longer be read) is refused to them too. An argument that addresses a record without that declaration is not recognized, so\n * declare it. Declare `argumentsResource` on every write tool whose decisions representatives should answer.\n *\n * And it decides where a guarded agent's placeholders may go (#2292, #2848). For an agent that declares\n * `contentGuardrails.personalData`, the arguments of every tool that can change something are checked before it runs:\n * a `⟦withheld:…⟧` marker or a placeholder the conversation did not issue is refused whatever the tool declares, and\n * an issued placeholder is put back only into a field this resource declares to hold data of the same kind. A write\n * tool without `argumentsResource` (and whose result is not `RECORDS_OF_RESOURCE`) accepts no placeholder at all.\n */\n argumentsResource?: FunctionTool_ArgumentsResource;\n /**\n * The argument that names a FILE the person approves (#2904): a generated document, an agent's output file, a report to\n * send. Declare it on an approval-gated tool whose call is about a file, so that what the person approves is the file's\n * BYTES and not merely its id:\n *\n * - the decision's card binds the file by its content hash (hashed now when the file has none), so an answer given on a\n * card shown before the file's recorded hash changed is refused as stale;\n * - the approval's seal commits to `H(salt ‖ contentSha256)` and attests the file, which is then frozen while the seal\n * exists (its bytes are not removed or replaced on request), and a verifier given the file's bytes reports a file\n * changed since the approval;\n * - an approver may not edit this argument: approving another file than the one shown is not an approval of it.\n *\n * A file the engine cannot hash (a remote reference whose vendor keeps the bytes, a deleted or missing file, a file of\n * another organization) is shown and sealed as NOT bound, never bound to an empty hash.\n *\n * Registration refuses it on a tool that is not approval-gated, on a question tool, and when the tool's argument schema\n * has no top-level string argument of that name. A tool without it is unaffected.\n */\n deliverableFileArgument?: string;\n /**\n * The electronic signature the file deliverable needs once the person approved it (#2293): after the approval's seal is\n * SEALED, the engine sends the approved file (`deliverableFileArgument`, bound by its hash) to the vendor selected for\n * `ELECTRONIC_SIGNATURE`, for `signers` to sign at `requiredLevel`, and records a `signatureRequests` row. Only a\n * validated signed document makes that request SIGNED. Opt-in per deliverable: a tool without it is unaffected.\n *\n * Requires `deliverableFileArgument`, an approval gate, and the `ELECTRONIC_SIGNATURE` capability enabled with a\n * provider that applies `requiredLevel`: the application refuses to start otherwise, so a requirement nothing could meet\n * is found before the first approval rather than after it.\n *\n * @example\n * electronicSignature: { requiredLevel: ElectronicSignature_Level.ADVANCED, signers: [FunctionTool_SignerSource.APPROVER] },\n */\n electronicSignature?: FunctionTool_ElectronicSignatureRequirement;\n /**\n * The tool IS a question to the person whose turn it is (#2720). Set by {@link askPersonTool}; do not set it on a\n * tool you write by hand.\n *\n * Its approval is not an approval: the turn pauses on the call as on any gated tool, but the person is shown the\n * call's QUESTIONS through a form and answers them, and the answer becomes the tool's result. Such a pause is settled\n * by an answer carrying the person's values, or by declining, and never by a bare approve, which would run the tool\n * on whatever answers the model wrote. It must be gated on the OWNER route: only the person in the conversation\n * answers it (a question to a reviewer belongs to an actor system's run).\n */\n asksThePerson?: boolean;\n /**\n * For a question tool (`asksThePerson`): whether the engine composes a form for its questions (#2720 D). `false` asks\n * them through the request's default form, exactly as written: a text box, the options, a yes or no. For a host whose\n * questions invite free answers (\"none\", \"contact us\", \"not decided yet\") that a typed control would refuse, such as\n * the creation workbench's interview (#2731). Absent: composed.\n */\n composesQuestionForm?: boolean;\n /**\n * For a question tool: what the agent is told when the person declines, in place of `ASK_PERSON_DECLINED_REASON`.\n * A host whose own rules say what to do without an answer (propose answers for the person to review, say) names\n * them here, so the agent is not told two different things.\n */\n questionDeclinedReason?: string;\n /**\n * The tool SHOWS its person records: the conversation draws a successful call as the records' summary cards, read\n * back from the call's input, rather than as a tool card. Set by {@link presentRecordsTool}; do not set it on a tool\n * you write by hand, whose input would not read back as records.\n */\n presentsRecords?: boolean;\n /**\n * The resources the tool SEARCHES through the retrieval index (#2300). Set by {@link retrievalTool}; startup refuses an\n * application whose retrieval tool names a resource that declares no `.ragSource()` field, which would otherwise\n * search nothing and answer as if nothing matched.\n */\n retrievalSources?: readonly ResourceType[];\n /**\n * What this tool's RESULT carries, so an agent declaring `contentGuardrails.personalData` (#2292) can treat its personal\n * fields before the model reads them. Declare it on every tool you write by hand: startup refuses a guarded agent\n * offered a tool that does not say, because an undeclared result could carry anything. An organization's policy can put\n * ANY language-model agent under a treatment (#2292 R8); an undeclared tool's result then reaches that agent's model\n * withheld whole, and startup warns about every such tool.\n *\n * - `{ kind: RECORDS_OF_RESOURCE, resourceType }` — records of that resource: a record, or `{ data: [records] }`. Their\n * personal fields are treated; for a tool that WRITES them, a placeholder in its arguments is put back too (only into\n * a field of the same kind). A row of an organization-owned resource is treated under its organization's agent\n * policy too (#2877), so the engine must know whose row it is (#3369). It does when the row keeps its\n * `organizationId`, and for a `PRINCIPAL_RESOURCE_OPERATION` tool whatever the row keeps, because each dispatch\n * records the owners of the rows it returned (as long as the operations it dispatches return rows naming their\n * organization: a custom operation's answer that names none leaves the call's rows to the strictest policy). A tool reaching its rows any other way declares\n * `rowsNameTheirOrganization: true` once every row it returns carries `organizationId`; without it, startup names the\n * tool, and a row naming no organization read by an agent acting in none is treated under the strictest policy.\n * - `{ kind: NOT_FROM_RECORDS, reason }` — nothing the engine moved from a record (an id list, a computed total, the\n * answer a person chose to give). Say why: the reason is what a reviewer reads.\n * - `{ kind: TREATED_BY_TOOL, treat }` — the tool knows its own shape and treats it (the engine's retrieval tool).\n *\n * `resourceReadTool`, `resourceWriteTool`, `presentRecordsTool`, `askPersonTool` and `retrievalTool` declare it for you.\n * The model is sent the treated result; the person, the conversation's tool trace and the cards keep the real values.\n */\n personalDataOutput?: FunctionTool_PersonalDataOutput;\n /**\n * How this tool reaches the application's data, and so on whose authority (#2839). The engine closes every tool over\n * its caller's server-verified `auth`; what it does with that inside `execute` is the tool's own code, which nothing\n * can check, so it is declared here:\n *\n * - `{ kind: PRINCIPAL_RESOURCE_OPERATION }` — every data access is {@link dispatchResourceOperationAsTool} (the\n * operation's roles, the tenancy filter and its rate limit, for the caller);\n * - `{ kind: PRINCIPAL_SCOPED_SERVICE, reason }` — a service given a context built from the caller's `auth`;\n * - `{ kind: NO_APPLICATION_DATA, reason }` — the tool touches no application data;\n * - `{ kind: SYSTEM_AUTHORITY, reason }` — it reaches data through a `*AsSystem` door, beyond the caller's own reach.\n *\n * `resourceReadTool`, `resourceWriteTool`, `presentRecordsTool`, `askPersonTool` and `retrievalTool` declare it for you.\n * Declare it on every tool you write by hand: the evidence an application's `WILDO.AI.AGENT_AUTHORITY_CONFINEMENT`\n * claim rests on lists every tool with its declaration, and reports one that declares nothing. It is never refused at\n * registration.\n */\n authority?: FunctionToolAuthorityDeclaration;\n /**\n * #2292: the result is the words of the PERSON the agent works for — the answer they gave to its question — and not\n * content somebody else wrote. An agent's prompt-injection screening (`contentGuardrails.promptInjection`) does not\n * screen it: the person's own words, on their own authority, are not a third party's injection. Set by\n * {@link askPersonTool}. It opts a result out of a security control, so registration refuses it on any tool that is not\n * a question tool (`asksThePerson`).\n */\n returnsThePersonsOwnWords?: true;\n}\n\n/** How a tool's result relates to personal data. See {@link FunctionTool.personalDataOutput}. */\nexport enum FunctionToolPersonalDataOutputKind {\n /** Records of one resource: a record, or `{ data: [records] }`. */\n RECORDS_OF_RESOURCE = 'records_of_resource',\n /** Nothing the engine moved from a record. */\n NOT_FROM_RECORDS = 'not_from_records',\n /** The tool treats its own result. */\n TREATED_BY_TOOL = 'treated_by_tool',\n}\n\n/** See {@link FunctionTool.personalDataOutput}. */\nexport type FunctionTool_PersonalDataOutput =\n | {\n readonly kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE;\n readonly resourceType: ResourceType;\n /**\n * #3369: every row this tool returns carries its resource's `organizationId` (the organization row its own `_id`).\n * For a tool that does not reach its rows through `dispatchResourceOperationAsTool`, whose owners the engine\n * therefore cannot observe. Checked on every row: one that still names no organization is treated under the\n * strictest policy, and counted on the call's operation record.\n */\n readonly rowsNameTheirOrganization?: true;\n }\n | { readonly kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS; readonly reason: string }\n | {\n readonly kind: FunctionToolPersonalDataOutputKind.TREATED_BY_TOOL;\n /** The result as the model may read it, every personal value replaced through `guard`. */\n readonly treat: (output: unknown, guard: PersonalDataGuard) => unknown;\n };\n\n/** The resource a tool's arguments describe. See {@link FunctionTool.argumentsResource}. */\nexport interface FunctionTool_ArgumentsResource {\n resourceType: ResourceType;\n /** The argument holding the id of the row the call acts on, when there is one. */\n rowIdArgument?: string;\n}\n\n/**\n * How an approval-gated tool routes its decision. See {@link FunctionTool.humanApproval}.\n */\nexport interface FunctionTool_HumanApprovalGate {\n route: HumanDecision_RouteKind;\n /**\n * How risky the CALL this gate holds is, in the vocabulary a resource operation declares its own risk in (#2526).\n * Every surface that answers the decision reads it: HIGH and CRITICAL put Approve behind a confirmation, and the\n * inbox can sort by it. Absent means no badge and no confirmation, never a default: a severity nobody declared would\n * be a claim nobody made.\n *\n * Declare what the operation the tool performs declares. A tool that deletes through an operation declared HIGH\n * declares HIGH here, so the person approving the call is warned exactly as one deleting the record by hand is.\n *\n * It is declared rather than derived because a hand-written tool names no operation: its `execute` may run several,\n * or none, and `argumentsResource` names the resource its arguments describe, not the verb. A `resourceWriteTool`\n * does know its operation, and still declares the risk here (pass `humanApproval: { route, riskLevel }`): the\n * boolean `requiresHumanApproval` carries no risk. The actor system's own `riskLevel` says how much an assistant may\n * be trusted overall, which is a different statement from how much this one call can do, so it is never shown in\n * place of this.\n */\n riskLevel?: ResourceOperationRiskLevel;\n /**\n * ROLE and ASSIGNEE: the role every answerer must hold. For ROLE it is the role the decision is\n * routed to. It is also the floor for anyone the decision is later reassigned, escalated or claimed\n * to: a move can never hand it to someone this gate would not have admitted.\n */\n eligibleRole?: string;\n /**\n * ROLE and ASSIGNEE: the professional qualifications every answerer must ALSO hold (#2967), kinds the application\n * declares in `professionalQualificationKinds`. Read when they act: a qualification verified, within its validity, and\n * recorded by the organization they decide for here — their own organization for one of its own members, the\n * representing organization for someone deciding through a relationship. A floor like `eligibleRole`: a reassignment,\n * an escalation or a claim can never hand the decision to someone without them.\n *\n * Use it when the decision must be taken by a person who is qualified, not merely one who holds a role: a chartered\n * accountant posting an adjustment, a licensed engineer signing off a design. Startup refuses a kind the application\n * does not declare, and an OWNER route (its answerer is the person whose turn it is, who is not vetted).\n *\n * ```ts\n * humanApproval: { route: HumanDecision_RouteKind.ROLE, eligibleRole: 'accountant', requiredQualificationKinds: ['chartered-accountant'] }\n * ```\n */\n requiredQualificationKinds?: readonly string[];\n /**\n * Whether the answer must carry a fresh step-up proof bound to THIS decision (#2923), as an operation approval's\n * `requiresApproval.requiresStepUpAuthentication` does. The person re-proves a factor (`POST /auth/reauth` with a\n * `decisionBinding` naming the decision and the presentation they answer) and answers from the decision inbox with it\n * in `X-Reauth-Token`. A socket or chat answer carries no proof, so it is refused (`decision_step_up_required`).\n *\n * Use it when approving the call commits the person to something they must be present for: releasing a payment,\n * signing off a filing. Applies to an agent's question (`askPersonTool`) the same way.\n */\n requiresStepUpAuthentication?: boolean;\n /**\n * What that step-up must ALSO be (#2923), with `requiresStepUpAuthentication: true`; startup refuses it without:\n * `maximumAgeSeconds` (at most 300) since the factor was proven, and a `minimumAssurance` of `reproven` (any step-up\n * factor), `possession` (TOTP or a passkey) or `phishing_resistant` (a passkey). The approvers' user types must allow\n * that factor as a step-up method. The factor and the instant it was proven are recorded on the decision and its\n * approval seal (`decider.stepUpMethod`, `decider.stepUpAt`).\n *\n * ```ts\n * humanApproval: {\n * route: HumanDecision_RouteKind.ROLE, eligibleRole: 'treasurer',\n * requiresStepUpAuthentication: true,\n * stepUp: { maximumAgeSeconds: 120, minimumAssurance: HumanDecision_StepUpAssurance.PHISHING_RESISTANT },\n * }\n * ```\n */\n stepUp?: HumanDecision_StepUpRequirement;\n /**\n * The channels that may answer the call (#2923): `web_session` (the application), `chat` (a chat card),\n * `api_client` (a client the person delegated to). Absent: every channel the other requirements allow. A tool approval\n * is decided in person, so `api_client` never answers one whatever this says; `chat` is refused beside a step-up, which\n * a chat answer cannot carry. A chat card for a call it may not answer links to it in the application.\n */\n answerChannels?: HumanDecision_AnswerChannels;\n /**\n * ASSIGNEE only: resolves the ONE person to route to, when the call pauses, from its arguments and\n * context (for example, the record's account manager). Returning `undefined`, or a person without\n * `eligibleRole`, refuses the pause and the call is denied — a decision nobody may answer is never\n * created.\n */\n assignee?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n /**\n * Where ESCALATE moves the decision when the person escalating names nobody. Resolves one person,\n * who is vetted against `eligibleRole` like any other target. Without it, an escalation must name\n * its target; there is no default escalation to administrators.\n */\n escalateTo?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n /**\n * When the decision should be taken, answered, and given up on (#1628). Optional: a gate declaring\n * nothing still gets a 24-hour lapse and two reminders — at half of it nobody has taken the decision,\n * at three quarters nobody has answered — sent to the people who may answer it.\n *\n * A deadline changes who is ASKED and who is TOLD, never what is decided. Missing one never approves\n * and never rejects; only the lapse ends the decision, as LAPSED, which is never counted as a refusal.\n *\n * ```ts\n * deadlines: {\n * lapseAfter: 'PT48H', // ISO-8601; always elapsed time\n * claim: { at: 'PT4H', basis: ReviewClockBasis.CALENDAR }, // counted in the application's reviewCalendar\n * decision: { at: { fractionOfLapse: 0.75 }, warnBefore: 'PT2H' },\n * rules: [\n * { stage: ReviewDeadlineStage.DECISION_WARNING, action: ReviewEscalationActionKind.NOTIFY },\n * { stage: ReviewDeadlineStage.DECISION_MISSED, action: ReviewEscalationActionKind.REASSIGN, target: resolveTeamLead },\n * ],\n * pauseStates: ['awaiting-requester-information'],\n * }\n * ```\n *\n * A declaration that could never do what it says stops the application at startup: a CALENDAR clock in\n * an application with no `reviewCalendar`, a target at or after the lapse, a REASSIGN rule with no\n * target or on an OWNER gate.\n */\n deadlines?: FunctionTool_HumanApprovalDeadlines;\n /**\n * What a person's DENIAL does to the record the call was about (#3015). A denied call does not run `execute`,\n * so without this a denial changes nothing: an agent's proposal stays proposed, and the application needs a\n * second, unsealed act to record the rejection. Declared here, the denial IS the rejection. It runs once the\n * sealed REJECTED decision has committed, like `execute` once an approval has, with the same context: the\n * requester's authority and the decision's `decisionRef`, which the effect reads back from the engine's record of\n * the decision rather than trusting.\n *\n * It runs only for a person's REJECTED answer, never for a lapse, a withdrawal, or the engine's own denial of a\n * call nobody can answer (nobody decided). It receives the arguments the model proposed (the denied call), and runs\n * in the agent's actor frame, so the rows it writes name the agent, the tool and the decision. Its failure never\n * undoes the decision: the denial stays sealed, the failure is logged, and the resumed turn is told that the record\n * did not move.\n *\n * The usual effect is a server-owned transition (an `INTERNAL_CALL` operation) on the row the call named, given\n * `ctx.decisionRef` and `ctx.executionId` so it can read the decision back before moving anything. The decision is\n * on the conversation's execution row, in whichever of `userFlowActorExecutions`, `organizationFlowActorExecutions`\n * and `applicationFlowActorExecutions` holds it: read each with `readAsSystem` on\n * `{ executionId, lastResolvedDecisionRef: decisionRef }` (the fields are backend-only, and a NOT_FOUND means the\n * next variant). The transition refuses unless `decisionOutcome` is `REJECTED`, `decidedByUserId` is set, and\n * `decisionToolName` equals `modelToolNameForFunctionRef(<this tool's functionRef>)`: the name the model saw, in\n * which a dot becomes `_`, never the dotted functionRef itself.\n *\n * ```ts\n * humanApproval: {\n * route: HumanDecision_RouteKind.ROLE,\n * eligibleRole: 'accountant',\n * onDenied: async (args, ctx) => {\n * const { proposalId } = PostProposal_InputSchema.parse(args); // the arguments the model proposed\n * const { resourcesRegistry, executionContextCreator, servicesRegistryHandler, authorizer } = ctx.services;\n * const contextIds = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n * const contextFor = (operation: string, path = resourcesRegistry.getServiceOperationPathDefault('proposals', operation)) =>\n * executionContextCreator.buildContextFromSocketAuth(ctx.auth, resourcesRegistry.getOperationFromPath(path), contextIds);\n * // An INTERNAL_CALL operation has no role gate of its own: the requester must hold the row's own UPDATE.\n * await authorizer.authorizeInController(proposalId, await contextFor(CoreResourceOperation.UPDATE,\n * resourcesRegistry.getOperationPathDefault('proposals', CoreResourceOperation.UPDATE)));\n * await servicesRegistryHandler.executeCustomOperation('proposals', 'record_denial', await contextFor('record_denial'),\n * proposalId, { decisionRef: ctx.decisionRef, executionId: ctx.executionId });\n * },\n * }\n * ```\n *\n * assurance-control: WILDO.AI.HUMAN_OVERSIGHT — a person's refusal of an agent's proposal takes effect on the record it refused, as the outcome of the sealed decision.\n */\n onDenied?: (args: unknown, context: FunctionToolExecutionContext) => Promise<void>;\n}\n\n/**\n * A gate's deadline declaration: the data {@link ReviewDeadlinesDeclaration} with a REASSIGN rule's\n * target resolver beside it. See {@link FunctionTool_HumanApprovalGate.deadlines}.\n */\nexport interface FunctionTool_HumanApprovalDeadlines extends Omit<ReviewDeadlinesDeclaration, 'rules'> {\n rules?: FunctionTool_ReviewEscalationRule[];\n}\n\n/** What one deadline stage does. Declared rules replace the default reminders. */\nexport interface FunctionTool_ReviewEscalationRule {\n stage: ReviewDeadlineStage;\n action: ReviewEscalationActionKind;\n /**\n * REASSIGN only, and required there: resolves the one person the decision moves to, from the call's\n * arguments, under the REQUESTER's authority as it stands when the stage fires. That person must be able\n * to answer it (hold the gate's `eligibleRole`, and not be the requester); if not, or if nobody resolves,\n * the rule notifies instead and the refusal is recorded. When several REASSIGN rules fire at one stage,\n * the first declared wins.\n */\n target?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n}\n\n/**\n * Whether a tool may be OFFERED to a turn, given where the turn's input came from (#1611). The one place\n * this is decided; the agents service asks it for every declared tool.\n *\n * Every tool is offered to an ordinary turn. An autonomous turn started by an inbound delivery is offered\n * only a tool that READS, or one gated on a REVIEWER — so a write that content from outside asks for is\n * either impossible or seen by a person first. An OWNER-gated tool is not offered there either: a machine\n * turn has no owner to ask, so the call could only ever be denied.\n *\n * A tool that SHOWS records (`presentsRecords`) is offered only to a turn a person watches in a conversation the\n * application draws. An A2A caller receives the reply's text and no tool calls, and an autonomous turn has nobody\n * watching: offered there, the agent would show cards nobody sees and leave them out of the text the reader does get.\n */\n// assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — a turn started by content from outside is offered no write a reviewer does not see first.\nexport function isFunctionToolOfferedToTurn(\n tool: Pick<FunctionTool, 'functionRef' | 'requiresHumanApproval' | 'humanApproval' | 'effect' | 'presentsRecords'>,\n autonomousTrigger: AutonomousTurnTrigger | undefined,\n initiationKind?: FlowsActors_InitiationKind | null,\n): boolean {\n if (tool.presentsRecords === true && (autonomousTrigger !== undefined || !turnIsDrawnForAPerson(initiationKind))) return false;\n if (autonomousTrigger !== AutonomousTurnTrigger.INBOUND_DELIVERY) return true;\n if (tool.effect === FunctionToolEffect.READ) return true;\n const route = resolveFunctionToolApprovalGate(tool)?.route;\n return route === HumanDecision_RouteKind.ROLE || route === HumanDecision_RouteKind.ASSIGNEE;\n}\n\n/**\n * The resource whose personal fields a guarded agent's placeholder may be put back into, in this tool's ARGUMENTS\n * (#2848): the resource the arguments describe (`argumentsResource`), else the resource of the records the tool returns\n * (`personalDataOutput: RECORDS_OF_RESOURCE`). `undefined` when the tool names neither: no argument may then carry a\n * placeholder, because nothing says which field of which resource it would land in.\n *\n * Keyed on the ARGUMENTS first because the result declaration says what the model is SENT, not what the tool WRITES: a\n * write whose result is only ids is `NOT_FROM_RECORDS`, and its arguments must still be checked.\n */\nexport function personalDataArgumentsResourceOf(tool: Pick<FunctionTool, 'argumentsResource' | 'personalDataOutput'>): ResourceType | undefined {\n if (tool.argumentsResource !== undefined) return tool.argumentsResource.resourceType;\n return tool.personalDataOutput?.kind === FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE ? tool.personalDataOutput.resourceType : undefined;\n}\n\n/**\n * Whether a guarded agent's arguments to this tool are checked and re-identified before it runs (#2848): every tool that\n * can change something (an undeclared `effect` counts as a write), and every tool that names a resource for its\n * arguments or its records. Only a pure read naming no resource passes its arguments as the model wrote them, since\n * nothing it does stores them.\n *\n * Until #2848 the check was keyed on the RESULT declaration alone, so a write tool declaring `NOT_FROM_RECORDS` stored a\n * `⟦withheld:…⟧` marker or a placeholder exactly as the model wrote it.\n */\n// assurance-control: WILDO.PRIVACY.DATA_MINIMIZATION — a guarded agent's write never stores a placeholder or a withheld marker, whatever its tool declares about its result.\nexport function functionToolArgumentsAreGuarded(tool: Pick<FunctionTool, 'effect' | 'argumentsResource' | 'personalDataOutput'>): boolean {\n return tool.effect !== FunctionToolEffect.READ || personalDataArgumentsResourceOf(tool) !== undefined;\n}\n\n/** One date-text form per schema: the SDK and the decision door ask for it on every call. See {@link toolCallSchemaOf}. */\nconst TOOL_CALL_SCHEMAS = new WeakMap<z.ZodTypeAny, z.ZodTypeAny>();\n\n/**\n * A parse output with every `Date` put back to the text (or epoch number) it was read from in `raw`, at the same place; a\n * `Date` with no such counterpart (one a transform or a default made) as its RFC 3339 text. Everything else as parsed.\n */\nfunction withDateText(parsed: unknown, raw: unknown): unknown {\n if (parsed instanceof Date) return typeof raw === 'string' || typeof raw === 'number' ? raw : parsed.toISOString();\n if (Array.isArray(parsed)) return parsed.map((item, index) => withDateText(item, Array.isArray(raw) ? raw[index] : undefined));\n if (parsed !== null && typeof parsed === 'object' && Object.getPrototypeOf(parsed) === Object.prototype) {\n const rawFields = raw !== null && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {};\n return Object.fromEntries(Object.entries(parsed).map(([key, value]) => [key, withDateText(value, Object.hasOwn(rawFields, key) ? rawFields[key] : undefined)]));\n }\n return parsed;\n}\n\n/**\n * A tool's arguments as the SDK holds a call (#3489): validated by the schema's JSON form, every check, refinement and\n * transform included, but with each DATE kept as the text it was written in rather than read into a `Date`.\n *\n * ## Why the SDK must never hold a `Date`\n *\n * The SDK treats a call's input as JSON data, and three of its mechanisms break on anything else:\n * - an approval-gated call is paused and stored as JSON, and on approval the SDK requires that parsing the call again\n * yields the stored input (`isDeepEqualData`). A `Date` comes back from storage as its text, so a date argument never\n * compared equal and the call could never be approved;\n * - the approval signature hashes the input with `canonicalJSON`, which writes a `Date` as `{}`: it covered no date's value;\n * - a person's edit is stored as written, and a date parsed to a `Date` never equals the person's text either.\n * spec-cite: N/A — read from the `ai@7.0.142` source (`generate-text/validate-tool-approvals.ts`, `util/is-deep-equal-data.ts`,\n * `util/canonical-hash.ts`), which documents none of it.\n *\n * So the text stays text up to `execute`, where {@link argumentsAToolExecutesWith} reads the dates (a value walk, no second\n * parse). The JSON Schema the model is told is the JSON form's own (a date is `string`, `date-time`): zod's pipe\n * processor is mirrored, since the wrapper's own input side is `any`.\n *\n * Rejected: restoring the stored call's `Date`s at the resume. It made the stored input equal again, but left the\n * signature blind to dates and an edit's text unequal; and the issue's other direction, refusing a gated tool that\n * declares `z.date()`, would forbid what the framework teaches applications to declare.\n */\nexport function toolCallSchemaOf(schema: z.ZodTypeAny): z.ZodTypeAny {\n const known = TOOL_CALL_SCHEMAS.get(schema);\n if (known) return known;\n const jsonForm = jsonParsingSchemaOf(schema);\n const callForm = z.any().transform(async (raw, ctx) => {\n const parsed = await jsonForm.safeParseAsync(raw);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) ctx.addIssue({ ...issue } as never);\n return z.NEVER;\n }\n return withDateText(parsed.data, raw);\n });\n callForm._zod.processJSONSchema = (ctx, _json, params) => {\n z.core.process(jsonForm, ctx as never, params as never);\n (ctx as unknown as { seen: Map<z.ZodTypeAny, { ref?: z.ZodTypeAny }> }).seen.get(callForm)!.ref = jsonForm;\n };\n TOOL_CALL_SCHEMAS.set(schema, callForm);\n return callForm;\n}\n\n/**\n * The schema the SDK validates this tool's calls against, which is also the one it revalidates an approved call with\n * (#3295): the tool's own, or under `TOKENIZE` the form whose personal fields also accept a placeholder, since a personal\n * value reaches the SDK as one. The ONE answer: the agent service hands it to the SDK and the decision door rehearses with\n * it, so the two read one schema.\n *\n * In its call form ({@link toolCallSchemaOf}): validated as JSON (#3478), a date's text kept (#3489). A model writes a tool\n * call as JSON, so a `z.date()` argument arrives as an RFC 3339 string; it is checked here, told to the model as `string`\n * `date-time`, and read into a `Date` only for `execute`.\n */\nexport function sdkInputSchemaOfFunctionTool(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n): z.ZodTypeAny {\n const argumentsResource = guard !== undefined && functionToolArgumentsAreGuarded(tool) ? personalDataArgumentsResourceOf(tool) : undefined;\n return toolCallSchemaOf(guard?.treatment === RedactionType.TOKENIZE && argumentsResource !== undefined\n ? placeholderTolerantInputSchema(tool.inputSchema, guard.personalFieldsOf(argumentsResource))\n : tool.inputSchema);\n}\n\n/**\n * The target fields of a guarded write whose tool names no resource for its arguments (#2848): none. Every issued\n * placeholder is then refused (\"that field does not hold data of the same kind\"), as is every withheld marker and every\n * placeholder the conversation did not issue, so the write can store only values the model actually wrote.\n */\nconst NO_PERSONAL_ARGUMENT_FIELDS: PersonalFieldMap = new Map();\n\n/**\n * What a tool's `execute` receives for the arguments the SDK hands it (#2292, #3295): under a guard, a placeholder is put\n * back (only into a field of the same kind) and the result held to the tool's own schema, which the placeholder-tolerant\n * one the model saw was not. Throws what the run would throw: a `PersonalDataPlaceholderRefusal` for a marker or a\n * placeholder that cannot be put back, a schema error for a value the tool refuses.\n *\n * The ONE body of that step: `execute` runs it, and the decision door rehearses it before a decision settles, so a call\n * cannot be recorded as accepted on an answer the run would refuse.\n */\nexport async function argumentsAToolRunsWith(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n args: unknown,\n): Promise<unknown> {\n if (!functionToolArgumentsAreGuarded(tool)) return args;\n if (guard === undefined) {\n // #2877: an unguarded call can still hold a withheld marker in its messages: a row an organization outside the call's\n // scope owns was withheld from its model (`treatRecordsResultByOwner`), and a resume after an approval pause runs with\n // no guard of that call. A marker stands for a value nobody may store, so it is refused here whatever the call, and the\n // decision door rehearses the same refusal. Nothing else changes for an unguarded call: no placeholder is put back and\n // the arguments are not parsed again.\n const carrying = argumentsCarryingWithheldMarkers(args);\n if (carrying.length > 0) {\n throw new PersonalDataPlaceholderRefusal(`${carrying.map((name) => `'${name}'`).join(', ')} carries a value you were not shown (⟦withheld:…⟧). Write a value you know, or leave the field out.`);\n }\n return args;\n }\n // Asynchronously, as the SDK validates: a tool may declare an async refinement, and `parse` would refuse every value of it.\n // The tool's own schema in its call form (#3478, #3489): a date is checked and kept as its text, as the SDK holds it, so\n // the decision door compares what a person read with what runs; `execute` reads it (`argumentsAToolExecutesWith`).\n return toolCallSchemaOf(tool.inputSchema).parseAsync(guard.reidentifyArguments(args, argumentFieldsOf(tool, guard)));\n}\n\n/**\n * What a tool's `execute` is called with (#3489): {@link argumentsAToolRunsWith}, with each date the tool's schema declares\n * read into a `Date`. The SDK holds a date as its text ({@link toolCallSchemaOf}), so this is where the tool gets the\n * `Date` its `z.date()` promises. A value walk on the schema's output side, never a second parse: the arguments are\n * already validated, and a transform must not run twice.\n */\nexport async function argumentsAToolExecutesWith(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n args: unknown,\n): Promise<unknown> {\n return ResourcesConfigOperationsDtosBuilderUtils.restoreStoredDates(await argumentsAToolRunsWith(tool, guard, args), tool.inputSchema);\n}\n\nfunction argumentFieldsOf(tool: Pick<FunctionTool, 'argumentsResource' | 'personalDataOutput'>, guard: PersonalDataGuard): PersonalFieldMap {\n const argumentsResource = personalDataArgumentsResourceOf(tool);\n return argumentsResource === undefined ? NO_PERSONAL_ARGUMENT_FIELDS : guard.personalFieldsOf(argumentsResource);\n}\n\n/**\n * #3295: {@link argumentsAToolRunsWith} rehearsed for the decision door, which must say why rather than throw: what\n * `execute` would receive (`ran`) beside the same arguments before its parse (`readAs`, the values a person reads), or the\n * arguments that stop it, by name. A value that cannot be put back is named alone, by asking the guard field by field; a\n * refusal it cannot place names every argument.\n */\nexport async function rehearsedToolArguments(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n executedCopy: Record<string, unknown>,\n): Promise<{ ran: unknown; readAs: unknown } | { refusedArguments: string[] }> {\n const guarded = guard !== undefined && functionToolArgumentsAreGuarded(tool) ? guard : undefined;\n try {\n return {\n ran: await argumentsAToolRunsWith(tool, guard, executedCopy),\n readAs: guarded ? guarded.reidentifyArguments(executedCopy, argumentFieldsOf(tool, guarded)) : executedCopy,\n };\n } catch {\n const unreadable = guarded === undefined ? argumentsCarryingWithheldMarkers(executedCopy) : Object.entries(executedCopy).filter(([name, value]) => {\n try {\n guarded.reidentifyArguments({ [name]: value }, argumentFieldsOf(tool, guarded));\n return false;\n } catch {\n return true;\n }\n }).map(([name]) => name);\n return { refusedArguments: (unreadable.length > 0 ? unreadable : Object.keys(executedCopy)).sort() };\n }\n}\n\n/**\n * Whether a turn's conversation is drawn for a person by the application: a turn over the application's own socket.\n * A turn that records no door predates the door's recording and was a socket turn. Total over the vocabulary.\n */\nfunction turnIsDrawnForAPerson(initiationKind: FlowsActors_InitiationKind | null | undefined): boolean {\n if (initiationKind === null || initiationKind === undefined) return true;\n const drawn: Record<FlowsActors_InitiationKind, boolean> = {\n [FlowsActors_InitiationKind.WEBSOCKET_SESSION]: true,\n [FlowsActors_InitiationKind.A2A_REQUEST]: false,\n [FlowsActors_InitiationKind.AUTONOMOUS]: false,\n // The reply is posted in Slack or Teams as text: a card the agent showed would reach nobody (#2665).\n [FlowsActors_InitiationKind.CHAT_MESSAGE]: false,\n };\n return drawn[initiationKind];\n}\n\n/** Refused because a tool's approval gate cannot be answered as declared. */\nexport class FunctionToolApprovalGateError extends Error {}\n\n/**\n * The approval gate a tool actually has, or `undefined` for an ungated tool. The ONE reader of the two\n * declarations, so no caller re-derives which one wins.\n *\n * Throws {@link FunctionToolApprovalGateError} for a declaration nobody could answer. The registry\n * calls it at registration, so that surfaces at startup rather than on the first gated call.\n */\n// assurance-control: WILDO.AI.HUMAN_OVERSIGHT — a gated tool's call waits for the person its gate routes it to.\nexport function resolveFunctionToolApprovalGate(tool: Pick<FunctionTool, 'functionRef' | 'requiresHumanApproval' | 'humanApproval' | 'asksThePerson'>): FunctionTool_HumanApprovalGate | undefined {\n const gate = tool.humanApproval ?? (tool.requiresHumanApproval ? { route: HumanDecision_RouteKind.OWNER } : undefined);\n // #2720: a question to the person is answered by the person in the conversation, so it is gated, on the OWNER route.\n if (tool.asksThePerson && gate?.route !== HumanDecision_RouteKind.OWNER) {\n throw new FunctionToolApprovalGateError(`Function tool \"${tool.functionRef}\" asks the person and must be gated on the OWNER route: only the person whose turn it is answers it.`);\n }\n if (!gate) return undefined;\n const refuse = (why: string): never => {\n throw new FunctionToolApprovalGateError(`Function tool \"${tool.functionRef}\" declares an approval gate nobody can answer: ${why}`);\n };\n refuseUnsoundDeadlines(tool.functionRef, gate);\n // #2923: a step-up declaration that cannot mean what it says is refused here, at registration.\n const stepUpIssues = [\n ...humanDecisionStepUpDeclarationIssues(gate, 'humanApproval'),\n // #2923: and a channel declaration that names a channel that could never answer it.\n ...humanDecisionAnswerChannelsIssues(gate.answerChannels, humanDecisionStepUpRequirementOf(gate) !== undefined, 'humanApproval'),\n ];\n if (stepUpIssues.length > 0) refuse(stepUpIssues.join(' '));\n // #2967: a required qualification names a kind, once each. Whether the application DECLARES it needs the configuration,\n // which a tool does not see: the startup validator asks that.\n const requiredKinds = gate.requiredQualificationKinds ?? [];\n if (requiredKinds.some((kind) => typeof kind !== 'string' || kind.length === 0)) refuse('`requiredQualificationKinds` names an empty kind.');\n if (new Set(requiredKinds).size !== requiredKinds.length) refuse('`requiredQualificationKinds` names a kind twice.');\n switch (gate.route) {\n case HumanDecision_RouteKind.OWNER:\n if (gate.eligibleRole || gate.assignee || gate.escalateTo) {\n refuse('an OWNER route is answered by the person whose turn it is, so it takes no role, assignee or escalation target.');\n }\n if (requiredKinds.length > 0) {\n refuse('an OWNER route is answered by the person whose turn it is, who is not vetted, so it can require no qualification; route it to a ROLE.');\n }\n return gate;\n case HumanDecision_RouteKind.ROLE:\n if (!gate.eligibleRole) refuse('a ROLE route must name `eligibleRole`, the role it is routed to.');\n if (gate.assignee) refuse('a ROLE route is answered by any holder of its role; `assignee` belongs to an ASSIGNEE route.');\n return gate;\n case HumanDecision_RouteKind.ASSIGNEE:\n if (!gate.eligibleRole) refuse('an ASSIGNEE route must name `eligibleRole`, the floor its assignee must meet.');\n if (!gate.assignee) refuse('an ASSIGNEE route must declare `assignee`, the resolver of the one person it is routed to.');\n return gate;\n default: {\n const unmapped: never = gate.route;\n return refuse(`unknown route \"${String(unmapped)}\".`);\n }\n }\n}\n/**\n * Who signs a deliverable sent for electronic signature (#2293). A closed vocabulary: each member names where the person\n * comes from, so nothing the model wrote picks a signer.\n */\nexport enum FunctionTool_SignerSource {\n /** The person whose approval of the call was sealed: the approver signs what they approved. */\n APPROVER = 'approver',\n}\n\n/** A tool's electronic-signature requirement for its file deliverable (`FunctionTool.electronicSignature`, #2293). */\nexport interface FunctionTool_ElectronicSignatureRequirement {\n readonly requiredLevel: ElectronicSignature_Level;\n /** Who signs, in signing order. At least one; each source once. */\n readonly signers: readonly FunctionTool_SignerSource[];\n}\n\n/**\n * What is wrong with a tool's electronic-signature requirement (`electronicSignature`, #2293), one sentence per problem\n * with its remedy; empty when it is sound or absent. Read at registration, beside the deliverable's own declaration.\n */\nexport function functionToolElectronicSignatureDeclarationProblems(\n tool: Pick<FunctionTool, 'functionRef' | 'electronicSignature' | 'deliverableFileArgument'>,\n): string[] {\n const requirement = tool.electronicSignature;\n if (requirement === undefined) return [];\n const named = `Function tool \"${tool.functionRef}\" declares electronicSignature`;\n const problems: string[] = [];\n if (!tool.deliverableFileArgument) problems.push(`${named} and no deliverableFileArgument: only a file deliverable the approver approved by its hash can be sent for signature.`);\n if (!Object.values(ElectronicSignature_Level).includes(requirement.requiredLevel)) problems.push(`${named} with an unknown requiredLevel \"${String(requirement.requiredLevel)}\".`);\n const signers = Array.isArray(requirement.signers) ? requirement.signers : [];\n if (signers.length === 0) problems.push(`${named} with no signer: name at least one (FunctionTool_SignerSource).`);\n if (signers.some((signer) => !Object.values(FunctionTool_SignerSource).includes(signer))) problems.push(`${named} with an unknown signer source.`);\n if (new Set(signers).size !== signers.length) problems.push(`${named} naming one signer source twice.`);\n return problems;\n}\n\n/**\n * What is wrong with a tool's file-deliverable declaration (`deliverableFileArgument`, #2904), one sentence per problem\n * with its remedy; empty when it is sound or absent. Read at registration, on the schema the tool is registered with\n * (after `bindToResources`), so the argument the engine binds is the one the model is offered.\n */\nexport function functionToolDeliverableDeclarationProblems(\n tool: Pick<FunctionTool, 'functionRef' | 'deliverableFileArgument' | 'inputSchema' | 'requiresHumanApproval' | 'humanApproval' | 'asksThePerson'>,\n): string[] {\n const argument = tool.deliverableFileArgument;\n if (argument === undefined) return [];\n const problems: string[] = [];\n const named = `Function tool \"${tool.functionRef}\" declares deliverableFileArgument \"${String(argument)}\"`;\n if (typeof argument !== 'string' || argument.trim().length === 0) return [`${named}, which names no argument: name the argument holding the file's id.`];\n if (!tool.humanApproval && !tool.requiresHumanApproval) {\n problems.push(`${named} and is not approval-gated: a file deliverable is bound by the approval of the call, so gate it (humanApproval or requiresHumanApproval).`);\n }\n if (tool.asksThePerson) problems.push(`${named} and asks the person: a question approves no file.`);\n const shape = tool.inputSchema instanceof z.ZodObject ? (tool.inputSchema.shape as Record<string, z.ZodTypeAny>) : undefined;\n const declared = shape?.[argument];\n if (!declared) {\n problems.push(`${named}, which is not a top-level argument of its input schema: declare it there as the file's id (a string).`);\n } else if (!isStringArgumentSchema(declared)) {\n problems.push(`${named}, which is not a string argument: a file deliverable is named by its file id.`);\n }\n return problems;\n}\n\n/** Whether an argument schema is a string once its optional, nullable and default wrappers are removed. */\nfunction isStringArgumentSchema(schema: z.ZodTypeAny): boolean {\n let current: z.ZodTypeAny = schema;\n for (let depth = 0; depth < 8; depth += 1) {\n if (current instanceof z.ZodOptional || current instanceof z.ZodNullable || current instanceof z.ZodDefault) {\n current = current.def.innerType as z.ZodTypeAny;\n continue;\n }\n return current instanceof z.ZodString || (current as { def?: { type?: unknown } }).def?.type === 'string';\n }\n return false;\n}\n\n/** @wildo_source:part:end saas.backend.flows-actors.function-tool */\n\n/**\n * Refuse a deadline declaration that could never do what it says (#1628), at registration. The calendar\n * half (a CALENDAR clock with no `reviewCalendar`) needs the application configuration, which a tool does\n * not see, so the startup validator asks that one; everything else is decided here.\n */\nfunction refuseUnsoundDeadlines(functionRef: string, gate: FunctionTool_HumanApprovalGate): void {\n const deadlines = gate.deadlines;\n if (!deadlines) return;\n const issues = reviewDeadlinesDeclarationIssues(\n { ...deadlines, rules: deadlines.rules?.map(({ stage, action }) => ({ stage, action })) },\n { routeKind: gate.route, calendarDeclared: true },\n );\n for (const rule of deadlines.rules ?? []) {\n if (rule.action === ReviewEscalationActionKind.REASSIGN && !rule.target) {\n issues.push(`deadlines.rules REASSIGNs at ${rule.stage} but names no \\`target\\`; a reassignment is never inferred.`);\n }\n if (rule.action === ReviewEscalationActionKind.NOTIFY && rule.target) {\n issues.push(`deadlines.rules NOTIFIES at ${rule.stage} but names a \\`target\\`, which only a REASSIGN rule uses.`);\n }\n }\n if (issues.length > 0) {\n throw new FunctionToolApprovalGateError(`Function tool \"${functionRef}\" declares deadlines that cannot work:\\n - ${issues.join('\\n - ')}`);\n }\n}\n\n/**\n * The name a `functionRef` is exposed to the model under.\n *\n * A `functionRef` uses dots, and a model API accepts only the portable set\n * (`toPortableModelToolName`), so the two differ for every tool. An overlong ref is also shortened. ONE definition, because the mapping is used in opposite directions by two sites: the\n * turn BUILDS the tool set from refs, and a resume that re-signs a modified approval must find the\n * FunctionTool behind a name it reads back out of the model SDK's own message array. A second copy\n * of this expression would make an approval unmodifiable for exactly the refs the two spelled\n * differently.\n *\n * Not injective by construction (`a.b` and `a_b` collapse), and deliberately not made so: the\n * forward direction is what the model sees, and a reverse lookup resolves against ONE agent's\n * declared refs, where a collision is an authoring defect. The turn keeps the first ref and reports\n * the second, which is also the ref a reverse lookup finds first.\n */\nexport function modelToolNameForFunctionRef(functionRef: string): string {\n return toPortableModelToolName(functionRef);\n}\n\n/**\n * The label key one slot of a registered function tool is worded under (#2551): `flows_actors_tools.<model tool\n * name>.<slot>`, derived from the tool's `functionRef` through {@link modelToolNameForFunctionRef}.\n *\n * The labelling planner plans it from every `functionRef` an application registers, and the conversation reads it from\n * the trace's `toolName`, which IS that model tool name. Going through this one function is what keeps the two equal.\n */\nexport function functionToolLabelKey(functionRef: string, slot: FlowsActorsToolLabelSlot): string {\n return flowsActorsToolLabelKey(modelToolNameForFunctionRef(functionRef), slot);\n}\n\n/**\n * The agent an actor system converses through: its first AGENTIC actor bound to an agent. ONE definition, because a\n * conversation picks its agent by it and whatever reads a settled tool call back (an approval's edit, an exported\n * correction, #1923) must resolve the same agent's tools.\n */\nexport function chatAgentRefOfActorSystem(actorSystem: Pick<ActorSystem, 'actors'>): string | undefined {\n // The shared rule (`conversationalActorOf`), so the browser names the same actor the runtime runs (#2524).\n return conversationalActorOf(actorSystem.actors)?.agentRef;\n}\n\n/** Uniform, model-facing result shape for read tools. */\ninterface ResourceReadToolResult {\n data: unknown[];\n pagination?: unknown;\n truncated?: boolean;\n /**\n * The call carried a `searchQuery` and no search ran — the SEARCH it reached failed, or the resource exposes none — so\n * the answer is the filtered LIST, and these rows are NOT matches for the text (#2769). Said to the model in `note`, and\n * stored on the trace, so neither the reply nor the card presents every record as what the text found. A resource whose\n * SEARCH cannot take text is not offered `searchQuery` at all (`bindToResources`), so this marks a run-time failure.\n */\n searchQueryNotApplied?: true;\n /** What the model must know about this answer, in its own words; set only with {@link searchQueryNotApplied}. */\n note?: string;\n}\n\n/** What the model is told when its search text could not be applied (#2769). Model-facing, never shown to a person. */\nconst SEARCH_QUERY_NOT_APPLIED_NOTE = 'The searchQuery was NOT applied: the text search could not run this time. '\n + 'These are the records the filters allow, not records matching the text. Do not present them as matches; narrow with '\n + 'filters, or say the text search failed.';\n\n/**\n * Normalize a handler list/search result (array or paginated) to the tool result shape.\n *\n * `truncated` says MORE records matched than came back. A paginated answer is already cut to the page by the\n * repository, so its rows never exceed `limit`: what says more exist is the envelope's `total`. Reading only the row\n * count told the model (and the person, through the card) that 50 of 60 pending todos were all of them.\n */\nfunction toReadResult(result: unknown, limit: number): ResourceReadToolResult {\n if (Array.isArray(result)) {\n return { data: result.slice(0, limit), truncated: result.length > limit };\n }\n if (result && typeof result === 'object' && 'data' in result && Array.isArray((result as { data: unknown[] }).data)) {\n const paged = result as { data: unknown[]; pagination?: { total?: unknown } };\n const data = paged.data.slice(0, limit);\n const total = paged.pagination?.total;\n const truncated = paged.data.length > limit || (typeof total === 'number' && total > data.length);\n return { data, pagination: paged.pagination, truncated };\n }\n return { data: [] };\n}\n\n/**\n * Resolve the operation a tool DISPATCHES for `(resourceType, operationIdentifier)`: the\n * URL-BEARING default, and nothing else.\n *\n * ## The defect this closes — `authorize ≡ advertise ≡ execute`\n *\n * Both factories used to resolve through `getServiceOperationPathDefault`, and they dispatched\n * through the `ServicesRegistryHandlerBackendService` convenience verbs (`create` / `update` /\n * `list` / `search`), which re-resolve the same way. That resolver PREFERS an `INTERNAL_CALL`\n * default over the URL-bearing one — deliberately, because it is the SERVICE layer's native\n * transport and the trusted internal callers it was written for want exactly that. This plane is\n * not one of them: it faces an external principal and advertises a public operation to a model.\n *\n * So for a resource declaring BOTH defaults, the tool advertised one operation and executed\n * another — a different `requestDto` validating the model's arguments, a different response DTO,\n * a different `roles` declaration, and different prefix / postfix / custom-impl side effects.\n *\n * **Measured 2026-09-08, and exactly one resource declares both: `organizations` CREATE.** The\n * divergence there is not cosmetic. Its `INTERNAL_CALL` default is the transport registration owns,\n * so the shared CREATE prefix treats that path as registration-managed and SKIPS the\n * `org_type_creation_restricted` guard that confines creation-policy-managed organization types to\n * the registration flow; and the founding-owner postfix is registered on the DEFAULT `API_CALL`\n * variant ONLY, so the internal path writes no owner membership. An agent tool wired to\n * `resourceWriteTool(ORGANIZATIONS, CREATE)` therefore created a tenant with no owner — precisely\n * the stranded state `administrative-continuity-floors.md` exists to prevent — while also reaching\n * a restricted organization type. The MCP tool plane had already made this exact decision and wrote\n * down the reasoning (`McpServerBackendService.callTool`); this plane simply had not.\n *\n * ## Why \"no URL-bearing default\" now REFUSES, and why that is the safe direction\n *\n * This is a behaviour change, and it is intended. A resource whose only default for an identifier\n * is `INTERNAL_CALL` has NO HTTP surface, and its author reasoned from exactly that: `users` LIST\n * declares `roles: []` and says in as many words that the empty set \"is inert here precisely\n * because it is not URL-bearing\". A tool that dispatched it made a route-less, deliberately\n * unexposed operation reachable by an external agent — the opposite of what the declaration\n * assumed. Refusing is fail-closed, and the refusal names the resource and the operation so an app\n * author who genuinely wants that surface exposed can declare a URL-bearing default for it.\n *\n * @returns the URL-bearing default operation, or `undefined` when the resource declares none.\n */\nfunction resolveDispatchableOperation(\n principal: ResourceOperationDispatchPrincipal,\n resourceType: ResourceType,\n operationIdentifier: string,\n): ResourceConfiguration_Operation<any, any, any> | undefined {\n const { resourcesRegistry } = principal.services;\n // Non-throwing probe FIRST: `getOperationPathDefault` mints an alert-grade INTERNAL error on its\n // miss path, and merely CONSTRUCTING a Wildo error fires its backend actions (LOG / ALERT /\n // METRICS) before any `catch` could downgrade them. A resource with no URL-bearing default for\n // this identifier is an ordinary, expected shape here — not an incident.\n if (!resourcesRegistry.hasOperationPathDefault(resourceType, operationIdentifier)) {\n return undefined;\n }\n return resourcesRegistry.getOperationFromPath(\n resourcesRegistry.getOperationPathDefault(resourceType, operationIdentifier),\n );\n}\n\n/**\n * What a tool may learn about the application's resources when it is registered ({@link FunctionTool.bindToResources}):\n * the operation a tool would DISPATCH for `(resourceType, operationIdentifier)` — the URL-bearing default, by the same\n * rule a tool's dispatch resolves it — or `undefined` when the resource exposes none. One rule for what a tool offers\n * and what it runs, so the two cannot disagree.\n */\nexport interface FunctionToolResourceDeclarations {\n dispatchableOperationOf(resourceType: ResourceType, operationIdentifier: string): ResourceConfiguration_Operation<any, any, any> | undefined;\n /**\n * The field the resource's primary scope fills from the request's own context (`organizationId` for an organization\n * resource), or `undefined`. A read tool does not offer it as a filter: the conversation's scope decides it, and the\n * repository refuses a caller value that disagrees (`applyAuthoritativeContextFilterValue`), so offering it would only\n * give the model a way to be refused.\n */\n primaryScopeFieldOf(resourceType: ResourceType): string | undefined;\n}\n\n/** A calendar day or an instant, as a model writes one in a date-range filter. */\nconst ReadToolFilterInstantSchema = z.union([z.iso.date(), z.iso.datetime({ offset: true })]);\n\n/** A range that bounds nothing filters nothing, and an empty object reaches the repository as a value it cannot cast. */\nconst hasABound = (range: Record<string, unknown>): boolean => Object.values(range).some((bound) => bound !== undefined);\n\n/** A declaration's own type under `.optional()` / `.nullable()` / `.default()`, which say nothing about what it filters by. */\nfunction unwrapFilterDeclaration(declaration: unknown): unknown {\n let current = declaration;\n while (current instanceof z.ZodOptional || current instanceof z.ZodNullable || current instanceof z.ZodDefault) current = current.unwrap();\n return current;\n}\n\n/**\n * What a model may send for ONE declared filter field, or `undefined` for a declaration it cannot express — a\n * cross-resource filter reference (a function), or a shape this plane does not read. The same classes the search request\n * schema distinguishes (`createResourceSearchQueryRequestSchema`): an equality on an enum, a string, a number or a\n * boolean, and a range on a date, a number or a year-month. A date range is written as ISO strings here, since a model writes text, and\n * read back as instants by {@link readToolFilterOf}.\n */\nfunction readToolFilterFieldSchema(declared: unknown): z.ZodTypeAny | undefined {\n if (typeof declared === 'function') return undefined;\n if (isResourcesFilterNumberRangeSchema(declared)) return Resources_Filter_NumberRangeSchema.refine(hasABound, 'Give min, max, or both.');\n // A range of months (#3435), offered as the range alone: one month is the range that starts and ends with it, so the\n // model has one shape to write. Strict (the vocabulary is a strict object), so a bound under another vocabulary's name is refused here rather than\n // reaching the repository as a key no store compiles. Each bound keeps the vocabulary's `YYYY-MM` pattern.\n if (isResourcesFilterYearMonthRangeSchema(declared)) return Resources_Filter_YearMonthRangeSchema.refine(hasABound, 'Give startMonth, endMonth, or both.');\n const declaration = unwrapFilterDeclaration(declared);\n if (declaration instanceof z.ZodDate) {\n return z.strictObject({\n startDate: ReadToolFilterInstantSchema.optional().describe('The earliest date or instant to include (ISO 8601). A calendar day starts at 00:00 UTC. Omit for no lower bound.'),\n endDate: ReadToolFilterInstantSchema.optional().describe('The latest date or instant to include (ISO 8601). A calendar day includes the WHOLE day, to 23:59:59.999 UTC. Omit for no upper bound.'),\n }).refine(hasABound, 'Give startDate, endDate, or both.');\n }\n if (declaration instanceof z.ZodEnum) return z.enum(declaration.options as [string, ...string[]]);\n // A Zod 4 string FORMAT (`z.uuid()`, `z.email()`) is not `instanceof z.ZodString`; every one extends the core\n // `$ZodString`, which is what the search request schema's own builder asks too. The declared length bounds are\n // carried (#2815): the controller refuses a value past them (`assertCollectionFilterValuesMatchPublishedSchemas`), and\n // this tool dispatches around the controller, so its own parse is the only place they can be held. Formats are not:\n // a model filters by the value it read, whatever its shape.\n if (declaration instanceof z.core.$ZodString) {\n const declaredBounds = declaration as { readonly minLength?: number | null; readonly maxLength?: number | null };\n const atLeastOne = z.string().min(Math.max(1, declaredBounds.minLength ?? 1));\n return typeof declaredBounds.maxLength === 'number' ? atLeastOne.max(declaredBounds.maxLength) : atLeastOne;\n }\n if (declaration instanceof z.ZodNumber) return z.number();\n if (declaration instanceof z.ZodBoolean) return z.boolean();\n return undefined;\n}\n\n/** The fields a read tool may filter by, keyed as the operation declares them, with what each accepts. */\nfunction readToolFilterFieldsOf(operation: ResourceConfiguration_Operation<any, any, any> | undefined, primaryScopeField?: string): Record<string, z.ZodTypeAny> {\n const declared = (operation as { filterFields?: Record<string, unknown> } | undefined)?.filterFields ?? {};\n const fields: Record<string, z.ZodTypeAny> = {};\n for (const [key, declaration] of Object.entries(declared)) {\n if (key === primaryScopeField) continue;\n const schema = readToolFilterFieldSchema(declaration);\n if (schema) fields[key] = schema.optional();\n }\n return fields;\n}\n\n/** The keys of a range filter's object (a refined object keeps them on its `shape`), or `undefined` for any other filter. */\nfunction readToolRangeShapeOf(schema: unknown): Record<string, unknown> | undefined {\n return schema instanceof z.ZodObject ? (schema.shape as Record<string, unknown>) : undefined;\n}\n\n/** A field's filter as a model reads it in the tool's description: its name, and its values when it has a closed set. */\nfunction describeReadToolFilterField(key: string, schema: z.ZodTypeAny): string {\n const inner = schema instanceof z.ZodOptional ? schema.unwrap() : schema;\n if (inner instanceof z.ZodEnum) return `${key} (one of: ${(inner.options as string[]).join(', ')})`;\n const range = readToolRangeShapeOf(inner);\n if (range && 'startDate' in range) return `${key} (a date range: startDate / endDate)`;\n if (range && 'startMonth' in range) return `${key} (a range of months: startMonth / endMonth, each YYYY-MM, both included)`;\n if (range) return `${key} (a number range: min / max)`;\n return key;\n}\n\n/** An ISO calendar day (`2026-10-12`), as opposed to an instant. */\nconst ISO_CALENDAR_DAY = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst LAST_MILLISECOND_OF_A_DAY = 24 * 60 * 60 * 1000 - 1;\n\n/**\n * A date bound as the instant the repository compares with (`$gte` / `$lte`). A calendar-day END bound is the day's\n * last millisecond: a person asking for \"due by the 12th\" means the 12th included, and the day's midnight would leave out\n * everything due on it after 00:00. Calendar days are UTC days; the tool knows no time zone, and says so to the model.\n */\nfunction readToolDateBoundOf(bound: string, side: 'start' | 'end'): Date {\n const instant = new Date(bound);\n return side === 'end' && ISO_CALENDAR_DAY.test(bound) ? new Date(instant.getTime() + LAST_MILLISECOND_OF_A_DAY) : instant;\n}\n\n/**\n * Whether a read tool's SEARCH can take a text: it is `isSearchable` and names `searchableFields` — the predicate both\n * repositories refuse a term by (`repository-resource` and the PostgreSQL repository's search preflight, #2510).\n */\nfunction readToolSearchesText(search: ResourceConfiguration_Operation<any, any, any> | undefined): boolean {\n const declared = search as { isSearchable?: boolean; searchableFields?: readonly unknown[] } | undefined;\n return declared?.isSearchable === true && (declared.searchableFields?.length ?? 0) > 0;\n}\n\n/**\n * The repository filter for a read tool's `filters` argument: a date range's ISO strings as instants, every other value\n * as sent. `undefined` when nothing is filtered. The schema already admitted only declared keys and their shapes, and a\n * range with no bound; one is still dropped here, since an empty object reaches the repository as a value it cannot cast.\n */\nfunction readToolFilterOf(filters: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!filters) return undefined;\n const filter: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue;\n if (value && typeof value === 'object') {\n const range = value as Record<string, unknown>;\n if (!hasABound(range)) continue;\n if ('startDate' in range || 'endDate' in range) {\n filter[key] = {\n ...(typeof range.startDate === 'string' ? { startDate: readToolDateBoundOf(range.startDate, 'start') } : {}),\n ...(typeof range.endDate === 'string' ? { endDate: readToolDateBoundOf(range.endDate, 'end') } : {}),\n };\n continue;\n }\n }\n filter[key] = value;\n }\n return Object.keys(filter).length > 0 ? filter : undefined;\n}\n\n/** {@link resolveDispatchableOperation}, refusing rather than returning `undefined`. */\nfunction requireDispatchableOperation(\n principal: ResourceOperationDispatchPrincipal,\n plane: ResourceOperationSeamPlane,\n resourceType: ResourceType,\n operationIdentifier: string,\n): ResourceConfiguration_Operation<any, any, any> {\n const operation = resolveDispatchableOperation(principal, resourceType, operationIdentifier);\n if (!operation) {\n throw new Error(\n `${OPERATION_DISPATCH_PLANE_FACTS[plane].callerLabel} for \"${resourceType}.${operationIdentifier}\": the resource declares no default `\n + 'URL-bearing variant for this operation, so there is no publicly-advertised operation to dispatch. Declare an '\n + 'API_CALL default for it, or expose a different operation.',\n );\n }\n return operation;\n}\n\n/**\n * Apply the dispatched operation's OWN `roles` ACL — the gate this plane was missing entirely.\n *\n * ## What was broken\n *\n * A function tool dispatches a resource operation through\n * `ServicesRegistryHandlerBackendService`, i.e. it enters at the SERVICE tier. The service tier\n * applies the repository's contextual filter (tenancy, FK narrowing, unit narrowing, the anonymous\n * guard, the retention row-hide — all fail-closed) and the whole operation pipeline (Zod, enabled\n * conditions, custom impl, hooks). It applies NO role check, and that is deliberate and\n * load-bearing: its dominant population is authentication, SCIM provisioning, webhook routing and\n * sweeps, which run BEFORE a role-bearing principal exists. Enforcing declared roles there would\n * deny the reads that ESTABLISH identity.\n *\n * `AuthorizationsBackendService.authorizeInController` is therefore the ONLY place an operation's\n * declared `roles` are checked, and it is mounted at the CONTROLLER tier — the boundary, because\n * that is where an untrusted principal names an operation.\n *\n * **This plane is that boundary and did not ask.** A tool call arrives from an external principal\n * (an A2A agent's token, or a user's own WebSocket) naming an operation on their own authority, and\n * dispatched it with the role ACL unread. A caller whose roles the operation refuses, but whose\n * tenancy admits the row, succeeded — so `roles: [ORG_MEMBER]` on Wonder Todos' todos CREATE, and\n * `roles: [APP_USER]` on the organizations self-service CREATE, were both statements about the HTTP\n * door only. Worse, the factories' own JSDoc, the app's registration comment and\n * `authenticateExternalToken`'s contract all asserted the opposite, so the gap read as closed.\n *\n * The MCP plane, which faces the same class of caller through a different transport, has always run\n * this gate (`McpServerBackendService.callTool`). This is the same call, on the sibling plane.\n *\n * ## Collection vs row\n *\n * `idOrIds` is `undefined` for CREATE / LIST / SEARCH (collection: roles + parent scope) and the\n * addressed record id for UPDATE (row: additionally FK reachability and per-row access). Passing a\n * value in the row's place for a collection call would authorize a READ of a row whose id happens\n * to be a scope id — a question nobody asked, failing for the wrong reason.\n *\n * Refusals are recorded by the authorizer's own denial-audit funnel, so a tool call denied here\n * produces the same `RESOURCE_OPERATION_DENIED` evidence a denied HTTP request produces.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — an external caller reaching a resource operation\n * off the HTTP plane is held to that operation's own declared authority, through the same predicate.\n *\n * @throws AUTHORIZATION — surfaced to the model as a tool error, so the agent can say it was refused.\n */\nasync function authorizeToolDispatch(\n principal: ResourceOperationDispatchPrincipal,\n executionContext: ExecutionContext<any>,\n idOrIds?: string,\n): Promise<void> {\n await principal.services.authorizer.authorizeInController(idOrIds, executionContext);\n}\n\n/**\n * Charge ONE dispatch against the operation's own authored `rateLimit?` policy, before the\n * dispatch happens.\n *\n * ## What was broken\n *\n * `rateLimit?` is authored on an `API_CALL` variant and had exactly\n * two consumers: `RateLimitBackendService.checkPolicyForVariant` at the HTTP controller\n * pre-flight, and `McpServerBackendService.assertOperationRateLimitPolicy` on the MCP tool plane.\n * The factories below dispatch the SAME operations through the SAME service pipeline while\n * bypassing Express entirely, so the identical operation was throttled over REST, throttled over\n * MCP, and unthrottled as an agent tool.\n *\n * The exposure is larger here than on either of those planes, which is why this is not merely a\n * consistency fix. A2A's blanket per-principal cap (`A2A_EXTERNAL_TURN_RATE_MAX`) bounds TURNS,\n * and one turn's tool loop may issue arbitrarily many tool calls — so an operation declaring\n * `requestsPerMinute: 5` could be dispatched far more than five times a minute by an external\n * caller spending a single turn. MCP has no such multiplier: one `tools/call` is one dispatch, so\n * its transport cap bounds dispatches 1:1.\n *\n * ## The policy is read off the operation actually being DISPATCHED — which is now the right one\n *\n * This guard originally re-resolved the URL-bearing default for itself, because the factories\n * dispatched the `INTERNAL_CALL` default and `rateLimit?` does not exist on that variant at all —\n * so reading the dispatched operation would have made the guard permanently inert for precisely\n * the resources that declare both. That divergence is gone: {@link resolveDispatchableOperation}\n * makes the URL-bearing default the dispatched operation, and this function takes it as an\n * argument. Policy-source and dispatch-target are now the same object rather than two resolutions\n * that agreed by discipline — which is what stops them separating again.\n *\n * Reading a single declaration as the OPERATION's budget is the framework's own established\n * reading of the field, not an invention: `resources-config.shared.factory.ts` projects\n * `rateLimit: defaultApiCallVariant.rateLimit` onto every derived auto-variant, stating that \"a\n * single declaration on the default URL-bearing variant covers all derived auto-variants\".\n *\n * ## Subject: the CREDENTIAL, not the tenant\n *\n * See {@link resolveDeclaredPolicySubjectKey} for the full argument. In short, an authored\n * `requestsPerMinute` has always meant \"per CLIENT\" — the HTTP seam keys on the source IP — so\n * the faithful translation onto a plane whose callers are credentials is the credential, then the\n * delegated user, then the owning scope. Keying on the tenant would silently make the same\n * declared number several times stricter here than over REST for any tenant running more than one\n * agent. Every branch reads a SERVER-VERIFIED field of the caller's auth; nothing here may ever be\n * sourced from a tool argument, or the throttle becomes opt-out by a model choosing a fresh bucket.\n *\n * ## Scope: a THIRD bucket, deliberately\n *\n * `agent-tool:resource:<resource>:<operation>`, distinct from the HTTP seam's\n * `resource:<resource>:<operation>` and MCP's `mcp:resource:<resource>:<operation>`. The three\n * count different SUBJECTS (an IP, a credential, a credential on a different transport); one\n * shared bucket would mix identity spaces and let a browser's traffic spend an agent's budget.\n * A chat command counts in a fourth, `chat-command:resource:<resource>:<operation>` (#2666 S7): its\n * subject is the linked member, whose commands must not spend the budget of their own agent's tools.\n *\n * ## Ordering: AFTER authorization\n *\n * Reversed 2026-09-08, when the role gate landed beside it, and MCP's argument is adopted verbatim:\n * a caller who may not run the operation at all must be refused with AUTHORIZATION rather than told\n * how much of a budget they have, and must not consume a slot of a budget that is not theirs —\n * which would let an unauthorized caller exhaust an authorized one's quota. The HTTP route takes the\n * same order for a signed-in caller (#2949), and counts before authorization only a caller with no\n * verified identity, per source address.\n *\n * ## Postures\n *\n * - **No declared policy, or a non-HTTP default** -> no-op, zero Redis traffic. The overwhelmingly\n * common case: most operations declare nothing.\n * - **Unkeyable subject with a policy declared** -> REFUSE. This diverges from MCP's\n * proceed-and-log, and the reason is the tool-loop multiplier described above: there, an\n * unkeyed call is still bounded 1:1 by the transport's per-principal cap, so proceeding costs a\n * bounded amount; here an unkeyed turn could drive an uncounted, unbounded loop against an\n * endpoint whose author asked for a budget. The branch is structurally unreachable — a tool runs\n * only inside an authenticated turn, and an authenticated principal always carries one of the\n * four identity fields — so the refusal costs nothing today and cannot decay into a silent hole.\n * - **Limiter outage** -> propagates, exactly as it does over HTTP and MCP for the same declared\n * policy. An authored budget must not quietly become \"unlimited\" on one plane while it is a 500\n * on the others. (Contrast `assertExternalTurnWithinRate`, the framework-default abuse throttle,\n * which counts in process on an outage, #3275, because nobody declared it.)\n *\n * ## A refusal is recorded, once per subject per window (#3008)\n *\n * Each declared window's FIRST refusal (the limiter reports it through `onFirstRefusalOfWindow`) leaves one\n * `OPERATION_RATE_LIMIT_REFUSED` row naming this plane, the operation, the subject counted and the window, written by\n * `recordOperationRateLimitRefusal`, the helper the MCP plane uses too, against the execution context built for this\n * operation. Fire-and-forget through the optional `services.auditLogs`: the refusal is thrown without waiting, and a\n * plane assembled without the audit service still refuses, unrecorded.\n *\n * ## Call-site enumeration, so the next reader does not re-derive it\n *\n * The invariant is \"a resource operation dispatched on behalf of an external CLIENT is charged\n * against its declared budget\". Enumerated 2026-09-08 over every caller of the generic service\n * dispatch (`doByOperationPath` and the `ServicesRegistryHandlerBackendService` verbs):\n *\n * | Plane | Verdict |\n * |---|---|\n * | REST route (`ControllerResourceBackendService.doOperation`) | charged once — a signed-in person or a machine by `assertDeclaredRateLimitForHttpCaller` once authorized, per credential or person (`OperationDispatchPlane.HTTP_ROUTE`, #2949); anyone else by `assertDeclaredRateLimitForHttpAddress` → `checkPolicyForVariant`, IP-keyed |\n * | MCP `tools/call` (`McpServerBackendService`) | charged — `checkPolicyForSubject`, credential-keyed, its own path (`OperationDispatchPlane.MCP_TOOL`) |\n * | Agent function tool (here; reachable over A2A and the app WebSocket) | charged — this function |\n * | Chat command (`OperationDispatchPlane.CHAT_COMMAND`, #2666 S7) | charged — this function, through the same seam, in its own bucket |\n * | Queue job executor (`job-executor.backend.service.ts`) | **N/A** — a REPLAY of an operation already authorized, and already charged, at enqueue time (`isWorkerExecution: true`). Charging again would double-count one client request and throttle a background worker against a client's budget |\n * | Minion-scoped handler (`saas-minions-lib`) | **N/A** — same worker plane, one scope deeper |\n * | Custom controllers (SCIM, charts, flows-actors) | **N/A** — the separate authoring surface: they declare their own policy and call `checkPolicy` inline (SCIM does, with its own scope key) rather than inheriting a resource operation's |\n * | Engine-internal collaborators (auth, org, RAG, seeding, retention) | **N/A** — not client-driven; reached from a plane that already charged, or from a system path with no client at all |\n * | Agent retrieval tool (`retrievalTool`, #2300) | **N/A** — client-driven, but it dispatches no resource operation: it searches the index and re-reads each matched row at the service tier, as the HTTP feature that offers retrieval (an application's own `ask`-style operation) charges only its own operation and never those reads. Bounded by the turn's step limit and the A2A turn budget, not by a resource operation's |\n *\n * The rule that generalises: a NEW plane that dispatches a resource operation on a client's behalf\n * owes its own `checkPolicyForSubject` call — AND its own `authorizeInController`. Nothing\n * structural forces either; both fields are simply unread where nobody reads them, which is how\n * both the MCP plane and this one shipped unthrottled, and how this one shipped unauthorized.\n *\n * @throws RATE_LIMIT (429) carrying `context.retryAfterSeconds` — the same envelope the HTTP and\n * MCP seams throw, so one refusal vocabulary covers all three planes. The AI SDK surfaces it to\n * the model as a tool error, so the agent can tell the user it is being throttled.\n */\n// assurance-control: WILDO.OPERATIONS.AUTHENTICATED_BURST_LIMIT — an agent tool's or chat command's call past its operation's declared window is refused before dispatch, counted per client, and its window's first refusal recorded.\nasync function assertDeclaredOperationRateLimit(\n principal: ResourceOperationDispatchPrincipal,\n plane: ResourceOperationSeamPlane,\n operation: ResourceConfiguration_Operation<any, any, any>,\n resourceType: ResourceType,\n operationIdentifier: string,\n executionContext: ExecutionContext<any>,\n): Promise<void> {\n // Defensive: `resolveDispatchableOperation` already filters to URL-bearing variants, so this\n // narrow exists to reach `rateLimit` on the union rather than to exclude a reachable case.\n if (\n operation.variantType !== ResourceOperationVariantType.API_CALL\n ) {\n return;\n }\n const policy = operation.rateLimit;\n if (!policy) {\n return;\n }\n\n const subject = resolveDeclaredPolicySubject(principal.auth?.initiatorIds);\n const { callerLabel } = OPERATION_DISPATCH_PLANE_FACTS[plane];\n if (!subject) {\n throw new Error(\n `${callerLabel} for \"${resourceType}.${operationIdentifier}\": the operation declares a rateLimit policy but the `\n + 'caller carries no server-verified identity to count it against, so the declared budget cannot be honoured.',\n );\n }\n\n // #3008: each window's first refusal is recorded, naming this plane, through the one helper the MCP plane uses too.\n await principal.services.rateLimitService.checkPolicyForSubject(\n policy,\n declaredRateLimitScopeKey(plane, resourceType, operationIdentifier),\n declaredPolicySubjectKey(subject),\n principal.organizationId,\n {\n onFirstRefusalOfWindow: (refusal) => recordOperationRateLimitRefusal(\n { auditLogs: principal.services.auditLogs },\n { plane, resourceIdentifier: resourceType, operationIdentifier, subject, refusal, executionContext },\n ),\n },\n );\n}\n\n/**\n * Dispatch a resource operation from a function tool, carrying BOTH gates the service tier skips.\n *\n * ## What this exists to prevent (#556)\n *\n * A `FunctionTool` enters at the SERVICE tier. It never passes through Express, so two\n * controller-tier gates are simply absent from its path — the operation's declared `roles` ACL and\n * its declared `rateLimit?`. That skip is CORRECT for the service tier's intended caller (the\n * authentication reads that run before a role-bearing principal exists) and wrong for this plane,\n * whose caller is an external principal naming an operation on their own authority.\n *\n * The failure is quiet, which is what makes it worth a seam. Tenancy still applies — the\n * repository's contextual filter runs regardless — so an unauthorized tool returns the caller's own\n * tenant's rows and LOOKS like it works. Nothing throws and nothing logs. What is missing is only\n * the row-level `roles` ACL: a caller whose roles the operation refuses, but whose tenancy admits\n * the row, succeeds.\n *\n * Until this existed the two gates were applied by hand at three sites in this file, and both helpers\n * were module-private — so an application author writing their own tool could not discharge the\n * obligation even after reading about it. The engine's own rule\n * (`invariant-call-site-enumeration.md`) asks for the opposite: prefer making the invariant\n * unbypassable over applying it N times. **This is the shortest path to a dispatch, so the correct\n * path is also the easy one.**\n *\n * ## The order is authorize → charge → dispatch, and it is not arbitrary\n *\n * Authorization first, so an unauthorized caller cannot spend an authorized caller's quota. The\n * charge before the dispatch, so a refused budget costs no work. This is the same order the MCP\n * plane uses, deliberately — one refusal vocabulary across every plane that enters here.\n *\n * ## One id, two uses, and why that is safer than two parameters\n *\n * `recordId` addresses the row AND is the authorization subject, because at every existing call site\n * those are the same value: an UPDATE passes the id to both, a CREATE/LIST/SEARCH passes it to\n * neither. Splitting them into two parameters would make it possible to authorize a collection call\n * while dispatching a row call — a question nobody asked, failing for the wrong reason. A bulk\n * operation addressed by a FILTER passes `dispatchFilter` instead, which is never an authorization\n * subject because a filter-addressed operation IS a collection call.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — an external caller reaching a resource operation\n * off the HTTP plane is held to that operation's own declared authority, through the same predicate.\n *\n * @throws AUTHORIZATION when the operation's roles refuse the caller — surfaced to the model as a\n * tool error, so the agent can say it was refused. Recorded by the authorizer's own denial-audit\n * funnel, so the evidence matches a denied HTTP request.\n * @throws RATE_LIMIT (429) carrying `context.retryAfterSeconds`, the same envelope the HTTP and MCP\n * seams throw.\n * @throws NOT_FOUND when the resource declares no dispatchable operation under that identifier.\n */\nexport async function dispatchResourceOperationAsTool<TResult = any>(input: {\n ctx: FunctionToolExecutionContext;\n resourceType: ResourceType;\n /** A `CoreResourceOperation` member, or a custom operation identifier the resource declares. */\n operationIdentifier: string;\n /** The addressed row, for a row-scoped operation. Authorizes AND addresses; omit for a collection call. */\n recordId?: string;\n /** A filter addressing a COLLECTION, for a bulk operation. Never an authorization subject. */\n dispatchFilter?: any;\n /**\n * Parent / context resource ids used to build the scoped execution context, keyed by resource type\n * or field identifier. Omit for an operation the caller addresses with no parent scope — a\n * collection of an application-scoped resource.\n */\n contextIds?: Readonly<Record<string, string>>;\n /** The operation payload — the body for a write, the query options for a read. */\n data?: any;\n /** Repository options passed through, e.g. `{ paginated: true }` for a LIST envelope. */\n options?: any;\n}): Promise<TResult> {\n const { ctx, ...dispatch } = input;\n // #2666 S7: the tool plane's dispatch is the shared seam's, so a tool and a chat command cannot drift.\n return dispatchResourceOperationForPrincipal<TResult>({ plane: OperationDispatchPlane.AGENT_TOOL, principal: ctx, ...dispatch });\n}\n\n/**\n * The planes this seam serves (#2666 S7): every `OperationDispatchPlane` (`@wildo-ai/saas-models`) except MCP's\n * `tools/call` and the operation's own HTTP route (#2949), which count the declared policy on their own paths. MCP's reaches\n * the same gates through `McpServerBackendService.callTool`, as the plane table\n * on {@link assertDeclaredOperationRateLimit} records. Each plane counts its dispatches in a rate-limit bucket of its own\n * and names itself in its refusals (`OPERATION_DISPATCH_PLANE_FACTS`); everything else (the operation it may dispatch,\n * the context, authorization, the charge and the dispatch) is the one seam,\n * {@link prepareResourceOperationDispatchForPrincipal}.\n *\n * The vocabulary moved to `@wildo-ai/saas-models` for #3008, when the record of a declared-policy refusal started naming\n * the plane; this alias is what keeps the MCP and HTTP-route members out of the seam's entry points.\n */\nexport type ResourceOperationSeamPlane = Exclude<OperationDispatchPlane, OperationDispatchPlane.MCP_TOOL | OperationDispatchPlane.HTTP_ROUTE>;\n\n/**\n * Who a seam dispatch acts for: the principal's server-verified authority, the organization it acts in, and the services\n * the seam is built from. A {@link FunctionToolExecutionContext} is one; a chat command builds one from the linked member.\n */\nexport type ResourceOperationDispatchPrincipal = Pick<FunctionToolExecutionContext, 'auth' | 'organizationId' | 'services'>;\n\n/**\n * A resource operation resolved, scoped, authorized and charged for one principal, and not yet run (#2666 S7).\n *\n * Two phases because one plane must act between them: a chat command records that its run started (so a retry can never\n * run it twice) only after every refusal that can be decided in advance, and before the dispatch.\n */\nexport interface PreparedResourceOperationDispatch<TResult = any> {\n /** The URL-bearing default operation that will run. */\n readonly operation: ResourceConfiguration_Operation<any, any, any>;\n /** The context it runs in, built from the principal's verified authority for THIS operation. */\n readonly executionContext: ExecutionContext<any>;\n /**\n * Run it, once. The authorization and the charge covered one dispatch, so a second call refuses rather than running\n * the operation again on a budget spent once.\n */\n dispatch(data?: unknown, options?: unknown): Promise<TResult>;\n}\n\n/**\n * Prepare a resource operation dispatched on a principal's behalf off the HTTP route (#556, #2666 S7): resolve the\n * URL-bearing default, build the execution context from the principal's verified authority, authorize, then charge the\n * operation's declared budget in the plane's bucket. Every gate the service tier skips is applied here, in the order\n * {@link dispatchResourceOperationAsTool} documents, and nothing has run when it returns.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — every plane that reaches a resource operation off the HTTP route is held\n * to that operation's own declared authority and budget, through this one seam.\n * assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — an agent's tool dispatch is held to its principal's authority by the operation's own gates.\n *\n * @throws AUTHORIZATION when the operation's roles refuse the principal; RATE_LIMIT (429) when its budget is spent; an\n * Error naming the plane when the resource declares no URL-bearing default for the operation.\n */\nexport async function prepareResourceOperationDispatchForPrincipal<TResult = any>(input: {\n readonly plane: ResourceOperationSeamPlane;\n readonly principal: ResourceOperationDispatchPrincipal;\n readonly resourceType: ResourceType;\n /** A `CoreResourceOperation` member, or a custom operation identifier the resource declares. */\n readonly operationIdentifier: string;\n /** The addressed row, for a row-scoped operation. Authorizes AND addresses; omit for a collection call. */\n readonly recordId?: string;\n /** A filter addressing a COLLECTION, for a bulk operation. Never an authorization subject. */\n readonly dispatchFilter?: any;\n /** Parent / context resource ids the execution context is scoped by, keyed by resource type or field identifier. */\n readonly contextIds?: Readonly<Record<string, string>>;\n}): Promise<PreparedResourceOperationDispatch<TResult>> {\n const { plane, principal, resourceType, operationIdentifier, recordId, dispatchFilter, contextIds } = input;\n\n const operation = requireDispatchableOperation(principal, plane, resourceType, operationIdentifier);\n // Rebuild a scoped ExecutionContext from the PRINCIPAL's verified auth for THIS operation. Never\n // reuse one built for another operation: the scope it resolves is operation-specific.\n //\n // An omitted `contextIds` is an EMPTY scope map, never `undefined`. The field is optional because a\n // collection of an application-scoped resource has no parent to name, and `buildContextFromSocketAuth`\n // reads the map it is given (`Object.keys` on its first line, then the declared-scope filter). Passing\n // the absence through made the creation assistant's first real turn throw `Cannot convert undefined or\n // null to object` on every read of the workbench's own resources (2026-09-24, #1464) — while every pin\n // here stayed green, because the mocked creator ignored its third argument.\n const executionContext = await principal.services.executionContextCreator.buildContextFromSocketAuth(principal.auth, operation, { ...(contextIds ?? {}) });\n\n await authorizeToolDispatch(principal, executionContext, recordId);\n await assertDeclaredOperationRateLimit(principal, plane, operation, resourceType, operationIdentifier, executionContext);\n\n const operationPath = ResourcesConfig_OperationPathUtils.extractOperationPath(operation) as ResourceConfiguration_OperationPath<any, any>;\n const subject = recordId ?? dispatchFilter;\n let dispatched = false;\n\n return {\n operation,\n executionContext,\n dispatch: (data?: unknown, options?: unknown): Promise<TResult> => {\n if (dispatched) {\n return Promise.reject(new Error(`${OPERATION_DISPATCH_PLANE_FACTS[plane].callerLabel} for \"${resourceType}.${operationIdentifier}\": a prepared dispatch runs once.`));\n }\n dispatched = true;\n /*\n * The trailing `options` is OMITTED rather than passed as `undefined` when absent, so this seam\n * calls the dispatcher with exactly the arity each site used before it existed.\n *\n * Behaviourally the two are identical for an optional parameter. What differs is what a test can\n * see: the authorization and write pins here assert the dispatch with `toHaveBeenCalledWith`,\n * which is arity-exact, so a uniform five-argument call would have required editing four tests\n * that guard an authorization path. Preserving the shape proves the refactor changed nothing,\n * which is the property that matters most for the one seam every tool dispatch now goes through.\n */\n const result = options === undefined\n ? principal.services.servicesRegistryHandler.doByOperationPath(operationPath, executionContext, subject, data)\n : principal.services.servicesRegistryHandler.doByOperationPath(operationPath, executionContext, subject, data, options as RepositoryOptions);\n // #3369: the owners of the rows this dispatch returned, read from the RAW result before any tool projects it, recorded\n // into the tool call being observed (nothing outside an agent tool call). A row the tool returns without its\n // `organizationId` is then still attributed to the organization that owns it.\n return Promise.resolve(result).then((rows: TResult) => {\n // An unregistered resource counts as organization-owned, as the owner policy counts it (fail closed).\n const primaryScope = principal.services.resourcesRegistry.tryGetResourceConfiguration?.(resourceType)?.resourcePrimaryScope;\n observeDispatchedRecordOwners(resourceType, (primaryScope ?? ResourcePrimaryScope.ORGANIZATIONS) === ResourcePrimaryScope.ORGANIZATIONS, rows);\n return rows;\n });\n },\n };\n}\n\n/** {@link prepareResourceOperationDispatchForPrincipal}, then its dispatch, for a plane with nothing to do between them. */\nexport async function dispatchResourceOperationForPrincipal<TResult = any>(input: Parameters<typeof prepareResourceOperationDispatchForPrincipal>[0] & {\n /** The operation payload — the body for a write, the query options for a read. */\n readonly data?: unknown;\n /** Repository options passed through, e.g. `{ paginated: true }` for a LIST envelope, or an idempotency key. */\n readonly options?: unknown;\n}): Promise<TResult> {\n const { data, options, ...preparation } = input;\n const prepared = await prepareResourceOperationDispatchForPrincipal<TResult>(preparation);\n return prepared.dispatch(data, options);\n}\n\n/**\n * Is this a REFUSAL the read tool must never launder into a different operation?\n *\n * Exists for exactly one reason: the read tool's SEARCH branch degrades to a scoped LIST on any\n * throw, and a refusal swallowed there would silently become an UNGATED LIST — the guard present\n * and inert, which is worse than absent because it reads as enforced. Two refusal kinds qualify:\n *\n * - **RATE_LIMIT** — a declared budget is an application's statement about the endpoint, not a\n * reason to reach for a different one.\n * - **AUTHORIZATION** — stronger still. A denial has already been RECORDED by the authorizer's\n * audit funnel, so proceeding would leave a `RESOURCE_OPERATION_DENIED` row beside a request\n * that then succeeded, making the access trail describe something that did not happen.\n *\n * A genuine \"this resource has no URL-bearing SEARCH operation\" still degrades, unchanged.\n */\nfunction isNonDegradableRefusal(error: unknown): boolean {\n return isWildoBackendError(error)\n && (error.type === ErrorType.RATE_LIMIT || error.type === ErrorType.AUTHORIZATION);\n}\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.ask-person-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `askPersonTool` registers under unless told otherwise.\n */\nexport const ASK_PERSON_FUNCTION_REF = 'engine.ask-person';\n\n/**\n * A tool through which an agent pauses its turn to ask its person a structured question (#2720).\n *\n * The agent calls it with a title, a reason and its questions (each a free_text, a choice or a yes/no). The turn\n * pauses, and the person in the conversation is shown the questions through a form: the engine has a model lay them\n * out (an amount as an amount, a day as a day, groups under headings) and asks them through the automated form, in the\n * chat and in the decision inbox. The person sends the answers, which the tool returns to the agent as\n * `{ answers: { [ref]: value }, comment? }` (`humanDecisionAgentValues`: an amount as `{ amount: \"19.99\", currency }`, a\n * day as `YYYY-MM-DD`, a moment as an ISO 8601 instant, a range as `{ from, to }`, and `comment` when the person added\n * a note), or declines, and the agent is told to decide on its own.\n *\n * Register it on a backend module's `flowsActors.functionTools` and grant it to an agent by its ref\n * (`capabilities.tools.functionRefs`). Only a turn with a person in it can ask: the question is routed to the turn's\n * owner, and an autonomous turn has none, so its call is refused at once as nobody can answer it — as is any approval\n * routed to the owner of such a turn.\n *\n * Two options adapt it to a host: `composesForm: false` asks the questions through the default form exactly as written\n * (for questions that invite free answers a typed control would refuse), and `declinedReason` replaces what the agent\n * is told when the person declines.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [askPersonTool()] }\n * // the agent: capabilities: { tools: { functionRefs: [ASK_PERSON_FUNCTION_REF] } }\n */\nexport function askPersonTool(options?: {\n functionRef?: string;\n description?: string;\n /** `false` asks the questions through the default form, as written. See {@link FunctionTool.composesQuestionForm}. */\n composesForm?: boolean;\n /** What the agent is told when the person declines. See {@link FunctionTool.questionDeclinedReason}. */\n declinedReason?: string;\n}): FunctionTool {\n return {\n functionRef: options?.functionRef ?? ASK_PERSON_FUNCTION_REF,\n description: options?.description\n ?? 'Ask the person you are working with one or more questions, and wait for their answers. Use it when you need '\n + 'information only they have, or a choice only they can make, before you can go on. Ask for what you need in one '\n + 'call, and do not ask for anything you can find yourself. It returns { answers, comment }: each answer under its '\n + 'question\\'s ref (an amount as { amount, currency } with the amount in the currency\\'s main unit, e.g. \"19.99\"; a '\n + 'day as YYYY-MM-DD; a moment as an ISO 8601 instant; a range as { from, to }), and comment when the person added '\n + 'a note.',\n inputSchema: AskPerson_ToolInputSchema,\n requiresHumanApproval: true,\n asksThePerson: true,\n ...(options?.composesForm === false ? { composesQuestionForm: false } : {}),\n ...(options?.declinedReason ? { questionDeclinedReason: options.declinedReason } : {}),\n effect: FunctionToolEffect.READ,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS, reason: 'It returns the answer the person chose to give.' },\n authority: { kind: FunctionToolAuthorityKind.NO_APPLICATION_DATA, reason: 'It asks the person and returns their answer; it reads and writes no record.' },\n returnsThePersonsOwnWords: true,\n execute: async (args) => {\n // Reached only after the person answered: answering replaces `answers` with their values, and declining does\n // not run the tool. A call that arrives without them is refused rather than answered with nothing.\n const input = AskPerson_ToolInputSchema.parse(args);\n if (!input.answers) throw new Error('The person has not answered this question.');\n return { answers: input.answers, ...(input.comment ? { comment: input.comment } : {}) };\n },\n };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.ask-person-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.present-records-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `presentRecordsTool` registers under unless told otherwise.\n */\nexport const PRESENT_RECORDS_FUNCTION_REF = 'engine.present-records';\n\n/**\n * A tool through which an agent SHOWS its person the records it is talking about, in the conversation.\n *\n * The agent calls it with a resource type, the ids a read or write tool returned, and the view (`summary`, one card per\n * record). The conversation draws the call as those records' summary cards, with the turn's other work, above its reply.\n * Use it when a list of records says more than a sentence: the todos due this week, the record the agent just created\n * or changed, the candidates it is asking about.\n *\n * Only a reference is kept. The transcript stores a tool call's input and never its result, so the ids are what\n * survives a reload. The browser fetches each record with the viewer's own session whenever it draws the conversation,\n * in the organization the tool read in: a record the viewer cannot read shows as unavailable, and a card shows the\n * record as it was when the conversation was drawn, so a record changed later shows its change on the next draw (the\n * default description tells the agent to show a record again after changing it). A card opens its record when the\n * resource has a page in the application within the viewer's tenancy; otherwise it is drawn without a link.\n *\n * The tool reads each record as the person first, through the resource's own READ operation and its access rules, and\n * tells the agent which records the person sees (`shown`) and which they could not be shown (`unavailable`: missing,\n * or out of their reach, which answer alike). Any other refusal (the operation's roles, a rate limit, a fault) fails the\n * whole call.\n *\n * The tool's result is never stored, so the cards add no copy of a record to the requester's transcript. The agent's\n * reply is stored like any reply, and it names the records it shows.\n *\n * Offered only to a turn a person watches in a conversation the application draws: an external agent over A2A\n * receives the reply's text and no tool calls, and an autonomous turn has nobody watching, so neither is offered it\n * (`isFunctionToolOfferedToTurn`). On a later turn the agent does not see which records it showed (a turn replays the\n * conversation's text only), so it reads a record again before acting on it.\n *\n * `resourceTypes` are the resources the agent may show. Grant only resources it can already read. Each needs a READ\n * operation reachable over HTTP, and its summary is the resource's authored summary layout, else the engine's default\n * from its summary fields.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [presentRecordsTool({ resourceTypes: ['todos', 'todoLists'] })] }\n * // the agent: capabilities: { tools: { functionRefs: [PRESENT_RECORDS_FUNCTION_REF] } }\n */\nexport function presentRecordsTool(options: {\n resourceTypes: readonly [ResourceType, ...ResourceType[]];\n functionRef?: string;\n description?: string;\n}): FunctionTool {\n const resourceTypes = [...new Set(options.resourceTypes)] as [ResourceType, ...ResourceType[]];\n return {\n functionRef: options.functionRef ?? PRESENT_RECORDS_FUNCTION_REF,\n description: options.description\n ?? 'Show the person records you are talking about, as cards in the conversation: the records a question is about, '\n + 'what you just created or changed, or a short list they asked for. Pass the ids exactly as a read or write tool '\n + 'returned them, each once. The cards are drawn above your reply, so refer to them as above, name each record you show, and '\n + 'do not repeat the fields the cards carry. A card shows the record as it is when the conversation is drawn: '\n + 'after you change a record you showed, show it again. On a later turn, read a record again before acting on it. '\n + 'It returns { shown, unavailable }: tell the person when a record could not be shown.',\n inputSchema: PresentRecords_ToolInputSchema.extend({\n resourceType: z.enum(resourceTypes).describe('The kind of record to show.'),\n }),\n effect: FunctionToolEffect.READ,\n presentsRecords: true,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS, reason: 'It returns which record ids were shown or unavailable, never their fields.' },\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n execute: async (args: PresentRecords_ToolInput, ctx: FunctionToolExecutionContext): Promise<PresentRecords_ToolResult> => {\n const input = PresentRecords_ToolInputSchema.parse(args);\n if (!resourceTypes.includes(input.resourceType as ResourceType)) {\n throw new Error(`This tool shows only ${resourceTypes.join(', ')} records.`);\n }\n const resourceType = input.resourceType as ResourceType;\n // A resource exposing no URL-bearing READ cannot be drawn by the browser either: a refusal naming the operation,\n // never \"unavailable\".\n requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.READ);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n const readable = await Promise.all(input.ids.map(async (id) => {\n try {\n const record = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: CoreResourceOperation.READ, recordId: id, contextIds });\n return record !== null && record !== undefined;\n } catch (error) {\n // A missing row and a row out of the person's reach both answer NOT_FOUND on the row path, alike by design\n // (as `resourceReadTool`). Every other refusal (the operation's roles, a rate limit) fails the call.\n if (isWildoBackendError(error) && error.type === ErrorType.NOT_FOUND) return false;\n throw error;\n }\n }));\n return {\n shown: input.ids.filter((_id, index) => readable[index]),\n unavailable: input.ids.filter((_id, index) => !readable[index]),\n };\n },\n };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.present-records-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.retrieval-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `retrievalTool` registers under unless told otherwise.\n */\nexport const RETRIEVAL_FUNCTION_REF = 'engine.retrieve';\n\n/** What the agent sends: a question in its own words, and how many records it wants back at most. */\nexport const Retrieval_ToolInputSchema = z.object({\n query: z.string().trim().min(1).max(1000).describe('What to look for, in plain words: the question, or the facts you need.'),\n limit: z.number().int().min(1).max(20).optional().describe('The most matching passages to look at (default 8); several may come from one record.'),\n});\nexport type Retrieval_ToolInput = z.infer<typeof Retrieval_ToolInputSchema>;\n\n/**\n * How a search ENDED, which is what the agent must act on before it answers, and why this is not a boolean on whether\n * results came back. Only a healthy, unobstructed search may say \"nothing matched\": a refused, failed, unrun or\n * incomplete search has proved nothing about whether the information exists (#2300, carried over from the Wonder Todos\n * knowledge-base tool that had to write this for itself).\n */\nexport enum RetrievalToolOutcome {\n /** Quotable passages came back. `notes` may still qualify how much was covered. */\n MATCHED = 'matched',\n /** A healthy search found nothing, and no refusal or failed read obscured it. */\n NOTHING_MATCHED = 'nothing-matched',\n /** Sources were not admitted for this caller: nothing is known about whether the information exists. */\n REFUSED = 'refused',\n /** The search failed or could not run. */\n UNAVAILABLE = 'unavailable',\n /** Nothing usable came back from a search or a read stage that did not complete. */\n INCOMPLETE = 'incomplete',\n}\n\n/**\n * What the tool returns. Each result is one record, with the passages that matched, each naming the field it came from:\n * that pair (record, field) is the citation. `notSearched` names every source the caller could not search, and `notes`\n * says, in words the agent can repeat, everything that made the answer smaller than the index could support.\n */\nexport interface Retrieval_ToolResult {\n outcome: RetrievalToolOutcome;\n results: Array<{\n resourceType: ResourceType;\n recordId: string;\n /** The record's name, as the resource's summary describes it. */\n title: string;\n excerpts: Array<{ field: string; text: string }>;\n }>;\n notSearched: Array<{ resourceType: ResourceType; reason: string }>;\n notes: string[];\n searchStatus: RagRetrievalSearchStatus;\n embeddingStatus: RagRetrievalEmbeddingStatus;\n}\n\n/**\n * What `retrievalTool` tells the model, unless told otherwise. Exported so an application can ADD what its sources are\n * for (`${RETRIEVAL_TOOL_DESCRIPTION} Use it for questions about our policies.`) without losing how to read the outcome.\n */\nexport const RETRIEVAL_TOOL_DESCRIPTION =\n 'Search the application\\'s own documents and records for what you need to answer. Ask in your own words, as a '\n + 'focused question, not the person\\'s message pasted in. Read `outcome` before you answer. \"matched\": answer only '\n + 'from the returned passages, and say which record (title) each fact came from. \"nothing-matched\": a healthy search '\n + 'found nothing; say so, and do not answer from general knowledge as if it were grounded. \"refused\", \"unavailable\" or '\n + '\"incomplete\": you have learned nothing about whether the information exists; never report it as absent. `notes` '\n + 'says what made the answer incomplete, and `notSearched` the sources you may not search.';\n\n/**\n * A tool through which an agent answers from the application's own documents and records: it searches the retrieval\n * index (every field declared `.ragSource()`, files included) and returns the matching passages with what they came\n * from, so the agent can quote and cite them.\n *\n * It searches only the `resourceTypes` you name, each of which must declare a `.ragSource()` field (startup refuses one\n * that does not). It searches as the CALLER: a source whose READ operation the caller's roles refuse is not searched\n * and is named in `notSearched`, and a matching record the caller cannot read is dropped. So an agent can never quote\n * a document its person could not open. It only reads, so it is offered on every turn, including an autonomous turn\n * started by an inbound message; what it returns came from your own records and is still content, not instructions.\n *\n * The search's query embedding is charged to the turn's case and run like the turn's own model calls, and every row\n * it reads is attributed to the agent, as for any tool.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [retrievalTool({ resourceTypes: ['knowledgeDocuments'] })] }\n * // the agent: capabilities: { tools: { functionRefs: [RETRIEVAL_FUNCTION_REF] } }\n */\nexport function retrievalTool(options: {\n resourceTypes: readonly [ResourceType, ...ResourceType[]];\n functionRef?: string;\n description?: string;\n /** Characters of matched text returned per call (the retrieval service's own default when absent). */\n maxContextCharacters?: number;\n}): FunctionTool {\n const resourceTypes = [...new Set(options.resourceTypes)] as [ResourceType, ...ResourceType[]];\n return {\n functionRef: options.functionRef ?? RETRIEVAL_FUNCTION_REF,\n description: options.description ?? RETRIEVAL_TOOL_DESCRIPTION,\n inputSchema: Retrieval_ToolInputSchema,\n effect: FunctionToolEffect.READ,\n retrievalSources: resourceTypes,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.TREATED_BY_TOOL, treat: treatRetrievalToolResult },\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_SCOPED_SERVICE, reason: \"It searches the retrieval index with a context built from the caller's own auth, so only records the caller may read are returned.\" },\n execute: async (args: Retrieval_ToolInput, ctx: FunctionToolExecutionContext): Promise<Retrieval_ToolResult> => {\n const input = Retrieval_ToolInputSchema.parse(args);\n const retrieval = ctx.services.ragRetrieval;\n if (!retrieval) throw new Error('Searching documents is not available here.');\n // The caller's own authority, built from their verified auth on the READ of a declared source, exactly as a read\n // tool builds it. Retrieval derives each source's own READ context from it and applies its three gates; it takes\n // no tenancy argument, so this context is the only authority the search has.\n const operation = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceTypes[0], CoreResourceOperation.READ);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n const executionContext = await ctx.services.executionContextCreator.buildContextFromSocketAuth(ctx.auth, operation, contextIds);\n const result = await retrieval.retrieve({\n query: input.query,\n executionContext,\n resourceTypes,\n limit: input.limit ?? 8,\n ...(options.maxContextCharacters ? { maxContextCharacters: options.maxContextCharacters } : {}),\n });\n return retrievalToolResultOf(result);\n },\n };\n}\n\n/**\n * A retrieval result as a guarded agent's model may read it (#2292): a passage of a personal field is withheld whole, and\n * a record's title is reduced to the resource's name when the title is built from a personal summary field. The\n * citation (record id, field name) stays, so the agent can still say where an answer came from.\n */\nfunction treatRetrievalToolResult(output: unknown, guard: PersonalDataGuard): unknown {\n const result = output as Retrieval_ToolResult;\n if (!result || !Array.isArray(result.results)) return output;\n return {\n ...result,\n results: result.results.map((row) => {\n const personal = guard.personalFieldsOf(row.resourceType);\n const title = guard.summaryCarriesPersonalData(row.resourceType) ? (row.title.split(' — ')[0] ?? row.title) : row.title;\n return {\n ...row,\n title,\n excerpts: row.excerpts.map((excerpt) => {\n const categories = personal.get(excerpt.field);\n return categories === undefined ? excerpt : { ...excerpt, text: guard.withholdPassage(categories) };\n }),\n };\n }),\n };\n}\n\n/**\n * The agent's view of a retrieval: the records and their cited passages, how the search ended, and every reason the answer\n * is smaller than the index could support. Search health always passes through, so an empty result never reads as a\n * proof of absence on its own.\n */\nexport function retrievalToolResultOf(result: RagRetrievalResult): Retrieval_ToolResult {\n const results = result.rows.map((row) => ({\n resourceType: row.resourceType,\n recordId: row.resourceId,\n title: row.header,\n excerpts: row.passages.map((passage) => ({ field: passage.fieldName, text: passage.text })),\n }));\n const notSearched = result.refusedResourceTypes.map((refusal) => ({ resourceType: refusal.resourceType, reason: refusal.reason }));\n const { truncation } = result;\n const notes: string[] = [];\n let outcome: RetrievalToolOutcome;\n if (result.searchStatus === RagRetrievalSearchStatus.FAILED) {\n outcome = RetrievalToolOutcome.UNAVAILABLE;\n notes.push('The search failed. Do not claim the information does not exist; report the search as unavailable.');\n } else if (result.searchStatus === RagRetrievalSearchStatus.NOT_RUN) {\n outcome = notSearched.length > 0 ? RetrievalToolOutcome.REFUSED : RetrievalToolOutcome.UNAVAILABLE;\n notes.push('No search ran. Nothing has been learned about whether the information exists.');\n } else if (results.length > 0) {\n outcome = RetrievalToolOutcome.MATCHED;\n } else if (result.searchStatus === RagRetrievalSearchStatus.DEGRADED || result.embeddingStatus === RagRetrievalEmbeddingStatus.FAILED\n || result.embeddingStatus === RagRetrievalEmbeddingStatus.CEILING_REFUSED\n || truncation.droppedByReadFailure > 0 || truncation.droppedUnreadableRows > 0) {\n outcome = RetrievalToolOutcome.INCOMPLETE;\n notes.push('Nothing readable came back from an incomplete search. Do not infer that the information is absent.');\n } else if (notSearched.length > 0) {\n outcome = RetrievalToolOutcome.REFUSED;\n notes.push('Some sources could not be searched for this person. Do not infer that the information is absent.');\n } else {\n outcome = RetrievalToolOutcome.NOTHING_MATCHED;\n notes.push('The search found no match. Say so; do not answer from general knowledge.');\n }\n if (result.searchStatus === RagRetrievalSearchStatus.DEGRADED) notes.push('Some search paths were unavailable. Use what came back, but describe the search as incomplete.');\n if (result.embeddingStatus === RagRetrievalEmbeddingStatus.FAILED) notes.push('The search by meaning failed; only the search by wording ran, so coverage is incomplete.');\n // #3030: a plan's limit, not an outage, and worded so: the model should not report the search as broken.\n if (result.embeddingStatus === RagRetrievalEmbeddingStatus.CEILING_REFUSED) notes.push('The organization\\'s allowance for search by meaning is used up for this period; only the search by wording ran, so coverage is incomplete.');\n if (notSearched.length > 0 && results.length > 0) notes.push('Some sources could not be searched; the passages returned do not cover them.');\n if (truncation.droppedUnreadableRows > 0) notes.push(`${truncation.droppedUnreadableRows} matching record(s) were withheld because this person may not read them. Do not try to reach them another way.`);\n if (truncation.droppedByReadFailure > 0) notes.push(`${truncation.droppedByReadFailure} record read(s) failed. This is an operational failure, not a permission decision; the answer is incomplete.`);\n if (truncation.reachedHitLimit || truncation.reachedContextCharacterBudget) notes.push('More may match than was returned. A narrower question may find the rest.');\n return { outcome, results, notSearched, notes, searchStatus: result.searchStatus, embeddingStatus: result.embeddingStatus };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.retrieval-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.resource-read-tool facet:layer:backend facet:family:flows-actors\n *\n * Generic resource-read tool factory. Produces a {@link FunctionTool} that lets\n * an agent look up records of ONE resource type **scoped to the calling user**,\n * with that user's own visibility — no `systemAccessPolicy` bypass. Instantiate\n * it per resource an agent should be able to read (e.g. `resourceReadTool(TODOS)`),\n * making any registered resource agent-readable without hand-writing a tool.\n *\n * The tool dispatches the resource's PUBLIC, URL-bearing default LIST / SEARCH — the same\n * operation a REST client reaches — under a user `ExecutionContext` rebuilt from the caller's\n * socket auth, and applies that operation's own declared `roles` ACL through\n * `AuthorizationsBackendService.authorizeInController` before dispatching it. So the framework's\n * contextual filter AND the role ACL apply exactly as for the user's own request. (The role gate\n * is named explicitly because it does NOT come free with the service path: the service tier\n * applies tenancy and the operation pipeline and no role check, so a tool that merely dispatched\n * would run with the ACL unread — which is what this factory did until 2026-09-08.) A resource\n * that declares no URL-bearing default for the operation is REFUSED rather than served through its\n * route-less internal variant. WHO the caller is is NEVER taken\n * from the model — only the record `id`, `searchQuery`, `filters` and `limit` args are. Its `functionRef`\n * defaults to `resource.<resourceType>.read` — reference that exact string from\n * your agent's `capabilities.tools.functionRefs`. Import path:\n * `@wildo-ai/saas-backend-lib`.\n *\n * **Looking up one record by its id.** Pass `id` to read ONE record through the resource's\n * URL-bearing default READ — the same operation a REST client reaches — authorized as a row\n * call under the same role ACL and contextual filter. A record that does not exist and a record\n * the caller may not see both answer an empty `data`, deliberately alike, so a lookup never tells\n * a caller that a record they cannot see exists. When `id` is given, `searchQuery` is ignored.\n * A `searchQuery` matches a resource's searchable TEXT and never an id: an agent told to\n * \"resolve the id\" of a record the user already identified by id must pass it as `id`, because a\n * search for an id finds nothing and reads, to the model and then to the user, as \"no such\n * record\". A resource that declares no URL-bearing READ is refused, as for any operation it does\n * not expose.\n *\n * **Narrowing by a field's value.** The tool also offers `filters`: the filter fields the resource's\n * default SEARCH declares (else its LIST), each as it accepts values — one of an enum's values, a\n * string, a number, a boolean, or a `{ startDate, endDate }` / `{ min, max }` / `{ startMonth, endMonth }` range. They are bound\n * when the tool is registered, from the operation it dispatches, so the model is offered what that\n * operation's repository allows — less the primary scope's field (`organizationId`), which the\n * conversation's own context decides. A question about a status or a category is a filter, never a\n * `searchQuery`: a search for the word \"pending\" matches no title. Filters work with or without a\n * `searchQuery`, and a resource that declares none offers none. A calendar-day `endDate` includes\n * that whole day (UTC). The result's `truncated` says more records matched than came back.\n * `searchQuery` itself is offered only when the resource's SEARCH can take a text (`isSearchable`\n * with `searchableFields`); when a search fails at run time, the answer is the filtered list and\n * says `searchQueryNotApplied`, so it is never read as what the text found.\n *\n * @param resourceType the resource to expose (any registered `ResourceType`).\n * @param options optional `functionRef` / `description` / `defaultLimit` / `maxLimit` overrides.\n * @example\n * // in a backend module's `flowsActors.functionTools` contribution:\n * functionTools: [resourceReadTool(TasksManager_ResourceType.TODOS)]\n * // and on the agent:\n * capabilities: { tools: { functionRefs: ['resource.todos.read'], mcpRefs: [] } }\n */\nexport function resourceReadTool(\n resourceType: ResourceType,\n options?: { functionRef?: string; description?: string; defaultLimit?: number; maxLimit?: number },\n): FunctionTool {\n /** @wildo_source:part:end saas.backend.flows-actors.resource-read-tool */\n const defaultLimit = options?.defaultLimit ?? 50;\n const maxLimit = options?.maxLimit ?? 100;\n const lookUp = `Look up the \"${resourceType}\" records the current user may see, to answer their questions about them. `\n + `Pass \"id\" to fetch ONE record by its id.`;\n const onlyVisible = ` Only records the current user may see are ever returned.`;\n const description = options?.description ??\n `${lookUp} Otherwise optionally pass a free-text searchQuery, which matches record text and never an id.${onlyVisible}`;\n const baseShape = {\n id: z.string().min(1).optional()\n .describe('The id of ONE record to fetch. Use it whenever a record id is already known: no other argument matches an id.'),\n searchQuery: z.string().optional()\n .describe('Free text matched against the records\\' text (titles, descriptions). It never matches a status, a category or an id: to narrow by a field\\'s value, use filters.'),\n limit: z.number().int().min(1).max(maxLimit).optional(),\n };\n\n return {\n functionRef: options?.functionRef ?? `resource.${resourceType}.read`,\n effect: FunctionToolEffect.READ,\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE, resourceType },\n description,\n inputSchema: z.object(baseShape),\n /*\n * The filters this resource DECLARES, offered as an argument. Without them a model asked for \"my pending todos\" had\n * one tool for one question — free text — and searched for the word \"pending\" (which matches no title), found\n * nothing, then listed everything. Measured on Wonder Todos, 2026-10-09: two calls, `{\"searchQuery\":\"pending\"}` then\n * `{}`. The search operation already declares `status` among its filters, and the MCP door already advertises them.\n *\n * Bound from the operation this tool DISPATCHES when filtering (the default SEARCH, else LIST), by the same rule its\n * dispatch resolves it, so the fields offered are the fields that operation's repository allows, less the primary\n * scope field the conversation's own context decides. A resource that declares no filter keeps the base schema.\n */\n bindToResources: (resources) => {\n const search = resources.dispatchableOperationOf(resourceType, CoreResourceOperation.SEARCH);\n const operation = search ?? resources.dispatchableOperationOf(resourceType, CoreResourceOperation.LIST);\n const fields = readToolFilterFieldsOf(operation, resources.primaryScopeFieldOf(resourceType));\n const hasFilters = Object.keys(fields).length > 0;\n // A text to search is offered only when the operation it reaches can search text (#2769): authorize ≡ advertise\n // ≡ execute. Both repositories refuse a term on a SEARCH that is not `isSearchable` with `searchableFields`, so\n // offering one there could only ever be refused, then answered by a LIST that cannot apply it.\n const searchesText = readToolSearchesText(search);\n if (searchesText && !hasFilters) return undefined;\n const { searchQuery: _textSearch, ...withoutSearch } = baseShape;\n const shape = searchesText ? baseShape : withoutSearch;\n const fieldList = Object.entries(fields).map(([key, schema]) => describeReadToolFilterField(key, schema)).join('; ');\n const filterWords = hasFilters\n ? ` To find records by a field's value (a status, a category, a date range), pass filters${searchesText ? ' rather than a searchQuery' : ''}. Filterable: ${fieldList}.`\n : '';\n // An author's own description is kept as written; only the framework's says what the tool takes.\n const baseDescription = options?.description ?? (searchesText ? description : `${lookUp} These records cannot be searched by text.${onlyVisible}`);\n // Without a text search the schema is STRICT: a `searchQuery` sent anyway comes back to the model as an invalid\n // input it can correct, instead of being stripped and answered with every record (#2769).\n const objectOf = searchesText ? z.object : z.strictObject;\n return {\n inputSchema: objectOf({\n ...shape,\n ...(hasFilters ? {\n filters: z.strictObject(fields).optional()\n .describe(`Narrow to records whose fields have these values.${searchesText ? ' Combine with searchQuery or use alone.' : ''} Fields: ${fieldList}.`),\n } : {}),\n }),\n description: `${baseDescription}${filterWords}`,\n };\n },\n execute: async (args: { id?: string; searchQuery?: string; limit?: number; filters?: Record<string, unknown> }, ctx: FunctionToolExecutionContext): Promise<ResourceReadToolResult> => {\n const { servicesRegistryHandler, executionContextCreator } = ctx.services;\n const limit = typeof args?.limit === 'number' ? Math.min(args.limit, maxLimit) : defaultLimit;\n const searchQuery = typeof args?.searchQuery === 'string' && args.searchQuery.trim().length > 0 ? args.searchQuery.trim() : undefined;\n const filter = readToolFilterOf(args?.filters);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n\n /*\n * IDENTITY LOOKUP (#1038). This tool used to offer only SEARCH and LIST, and SEARCH matches a resource's\n * searchable TEXT. So an agent told to \"resolve its id with the read tool\" — the Todo Assistant's own\n * instruction — searched for an id, found nothing, and told its user that a record which existed did not.\n * Measured 2026-09-14: the same seeded row was returned by LIST and by a SEARCH on its title, and by a\n * SEARCH on its id not at all.\n *\n * READ is the operation that answers \"this record, by id\", so an id is dispatched there: a ROW call, with\n * the id as the authorization subject, under the operation's own role ACL and contextual filter — the same\n * seam UPDATE uses.\n */\n const id = typeof args?.id === 'string' && args.id.trim().length > 0 ? args.id.trim() : undefined;\n if (id) {\n // Outside the catch below on purpose: a resource exposing no URL-bearing READ is a refusal naming the\n // operation, and must never be read as \"not found\".\n const readOp = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.READ);\n let record: unknown;\n try {\n record = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.READ,\n recordId: id,\n contextIds,\n });\n } catch (error) {\n // A missing row and a row outside the caller's reach both answer NOT_FOUND on the row path, alike by\n // design. Both become an empty result, so the model can say \"no such record visible to you\" instead of\n // reporting a failure — and nothing distinguishes the two. Every other refusal (AUTHORIZATION from the\n // operation's roles, RATE_LIMIT) propagates unchanged.\n if (isWildoBackendError(error) && error.type === ErrorType.NOT_FOUND) return { data: [] };\n throw error;\n }\n if (record === null || record === undefined) return { data: [] };\n return { data: [await toResponseSafeToolOutput(readOp, record)] };\n }\n\n // Prefer SEARCH when a query or a filter is supplied AND the resource EXPOSES it (a search with no term and a filter\n // is the filter-only search the collection views run); fall back to a scoped LIST, which carries the same filter.\n // Both run as the user, under the operation's own role ACL (no bypass).\n if (searchQuery || filter) {\n // The fallback catch covers ONLY op-resolution + the search call — a resource may expose no\n // SEARCH operation, in which case we degrade to a scoped LIST. It deliberately does NOT wrap\n // the response-DTO projection below: a projection failure there is a real server contract\n // violation (a record that violates its own response DTO) and must surface as a tool error,\n // exactly as it would on the LIST path — never silently degrade to an unfiltered LIST.\n let searchOp: ResourceConfiguration_Operation<any, any, any> | undefined;\n let searchResult: unknown;\n try {\n // Non-throwing: a resource with no URL-bearing SEARCH default has nothing to expose here,\n // which is the documented degradation rather than a refusal.\n searchOp = resolveDispatchableOperation(ctx, resourceType, CoreResourceOperation.SEARCH);\n if (searchOp) {\n // The seam authorizes, charges and dispatches in that order. It sits inside this try\n // because that is where the dispatch is; the catch below re-throws either refusal so\n // neither can be laundered into an ungated LIST. The operation is resolved twice — once\n // above to decide whether SEARCH is even available, once inside the seam — and that is\n // deliberate: the availability question is this factory's, the gates are the seam's.\n searchResult = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.SEARCH,\n contextIds,\n data: { searchQuery: searchQuery ?? '', filter, page: 1, limit },\n });\n }\n } catch (error) {\n // A declared budget, or a role refusal, is a statement about THIS endpoint — not a reason\n // to reach for a different one. Degrading here would answer the model with LIST results\n // the caller was just refused: enforcement that reports success.\n if (isNonDegradableRefusal(error)) throw error;\n searchOp = undefined; // SEARCH failed to resolve or dispatch — fall through to LIST.\n }\n if (searchOp !== undefined) {\n // Project through the SEARCH operation's response DTO + JSON wire step, exactly as the\n // REST controller does, so no `Date`/backend-only/secret field reaches the model.\n const safeSearchResult = await toResponseSafeToolOutput(searchOp, searchResult);\n return toReadResult(safeSearchResult, limit);\n }\n }\n\n // LIST is a distinct operation with its own ACL and its own declared budget, so it is\n // authorized and charged separately. A call that resolved SEARCH and then degraded to LIST\n // does both twice — two operations were attempted, exactly as two HTTP requests would be, and\n // that path is only reached when the search dispatch failed for a reason that is not a refusal.\n const listOp = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.LIST);\n // `paginated: true` yields the `{ data, pagination }` envelope the LIST response DTO expects\n // (the same shape the HTTP controller requests) — a bare array would fail the wrapper-DTO\n // projection in `toResponseSafeToolOutput` below.\n const listResult = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.LIST,\n contextIds,\n // The filter rides LIST too: a failed SEARCH must never degrade into the UNFILTERED collection, which the model\n // would then report as the answer to the narrower question it asked.\n data: { filter, page: 1, limit },\n options: { paginated: true },\n });\n const safeListResult = await toResponseSafeToolOutput(listOp, listResult);\n const listed = toReadResult(safeListResult, limit);\n // A term reaches this LIST only when its SEARCH could not run, and LIST cannot apply it: say so rather than let\n // every record the filters allow read as what the text found (#2769).\n return searchQuery ? { ...listed, searchQueryNotApplied: true, note: SEARCH_QUERY_NOT_APPLIED_NOTE } : listed;\n },\n };\n}\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.resource-write-tool facet:layer:backend facet:family:flows-actors\n *\n * Generic resource-WRITE tool factory. The mutating sibling of {@link resourceReadTool}.\n * Produces a {@link FunctionTool} that lets an agent CREATE or UPDATE ONE resource\n * type **as the calling user**, under the caller's own `ExecutionContext` rebuilt\n * from their verified socket auth — no `systemAccessPolicy` bypass, and identity is\n * NEVER taken from the model. It dispatches the resource's PUBLIC, URL-bearing default CREATE /\n * UPDATE — the same operation a REST client reaches, with the same request DTO validating the\n * model's arguments and the same prefix / postfix side effects — and applies that operation's own\n * `accessControl` (roles + parent scope, plus per-row access on UPDATE) through\n * `AuthorizationsBackendService.authorizeInController` before the write. Authorization is therefore\n * **fail-closed**: a caller lacking the operation's role gets a thrown authz error, not a silent\n * write.\n *\n * Both halves of that are load-bearing and neither came free, so do not simplify them away. The\n * service tier applies tenancy and the operation pipeline and NO role check, and the service\n * layer's own default resolver PREFERS a route-less `INTERNAL_CALL` variant over the public one —\n * so before 2026-09-08 this factory dispatched a different operation from the one it advertises,\n * with the ACL unread. On `organizations` CREATE that combination created ownerless tenants.\n *\n * A resource that declares no URL-bearing default for the operation is REFUSED rather than written\n * through its internal variant. Owner FKs and other server-set fields are EC-injected / `excludeFromCreate`,\n * so the model can never spoof ownership through the tool arguments.\n *\n * **Retries.** A model calls a write tool again when a call fails, so an operation that declares\n * `idempotencyKey` takes the key as the `idempotencyKey` ARGUMENT: add\n * `idempotencyKey: z.string().describe(IDEMPOTENCY_KEY_TOOL_ARGUMENT_DESCRIPTION)` to `inputSchema` (`.optional()` for an\n * `ACCEPTED` operation). The factory takes it out of the fields and the framework answers the model's retry\n * with the first result instead of writing twice. A `REQUIRED` operation called without it is refused before\n * anything runs, naming the argument.\n *\n * Unlike the read tool (whose args are a fixed `{ searchQuery, limit }`), a write\n * tool's arguments are resource-specific, so the caller MUST supply the model-facing\n * `inputSchema` — the create/update field contract shown to the model. Keep it to the\n * fields the model should legitimately set. For `UPDATE`, include the record `id` in\n * the schema; the factory splits `id` out to address the row and passes the remaining\n * fields as the patch.\n *\n * `functionRef` defaults to `resource.<resourceType>.<op>` (e.g. `resource.todos.create`)\n * — reference that exact string from your agent's `capabilities.tools.functionRefs`.\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @param resourceType the resource to expose (any registered `ResourceType`).\n * @param op `CoreResourceOperation.CREATE` or `CoreResourceOperation.UPDATE`.\n * @param options `{ inputSchema, functionRef?, description? }` — `inputSchema` is REQUIRED (the model-facing argument contract).\n * @example\n * // in a backend module's `flowsActors.functionTools` contribution:\n * functionTools: [\n * resourceWriteTool(TasksManager_ResourceType.TODOS, CoreResourceOperation.CREATE, {\n * inputSchema: z.object({ title: z.string(), todoListId: z.string(), description: z.string().optional() }),\n * }),\n * ]\n * // and on the agent:\n * capabilities: { tools: { functionRefs: ['resource.todos.create'], mcpRefs: [] } }\n */\nexport function resourceWriteTool(\n resourceType: ResourceType,\n op: CoreResourceOperation.CREATE | CoreResourceOperation.UPDATE,\n options: {\n inputSchema: z.ZodTypeAny;\n functionRef?: string;\n description?: string;\n /**\n * Gate this write behind a HUMAN decision (see {@link FunctionTool.requiresHumanApproval}).\n *\n * Without this passthrough the flag was declarable only by hand-rolling a `FunctionTool`, so\n * the approval gate was unreachable from the factory every app author actually uses — a\n * capability present in the contract and absent from the authoring surface. Reads are not\n * offered the option: approval exists to gate EFFECTS, and gating a read teaches authors to\n * approve things reflexively, which is how an approval prompt stops being read.\n */\n requiresHumanApproval?: boolean;\n /** Route this write's approval to a reviewer (see {@link FunctionTool.humanApproval}). */\n humanApproval?: FunctionTool_HumanApprovalGate;\n },\n): FunctionTool {\n /** @wildo_source:part:end saas.backend.flows-actors.resource-write-tool */\n return {\n functionRef: options.functionRef ?? `resource.${resourceType}.${op}`,\n effect: FunctionToolEffect.WRITE,\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n requiresHumanApproval: options.requiresHumanApproval,\n humanApproval: options.humanApproval,\n // The arguments ARE the resource's fields (and `id` its row), so an exported correction reads their declarations (#1923).\n argumentsResource: { resourceType, ...(op === CoreResourceOperation.UPDATE ? { rowIdArgument: 'id' } : {}) },\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE, resourceType },\n description:\n options.description ??\n (op === CoreResourceOperation.CREATE\n ? `Create a new \"${resourceType}\" record on behalf of the current user from the provided fields. The record is owned by and scoped to the current user; ownership fields are set by the system, not from the arguments.`\n : `Update an existing \"${resourceType}\" record the current user owns. Pass the record \"id\" plus only the fields to change.`),\n inputSchema: options.inputSchema,\n execute: async (args: Record<string, unknown>, ctx: FunctionToolExecutionContext): Promise<unknown> => {\n const { servicesRegistryHandler, executionContextCreator } = ctx.services;\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n\n // UPDATE addresses a row; CREATE does not. Split FIRST, before anything is resolved: this is\n // a check on the tool AUTHOR's own `inputSchema`, independent of the registry, and surfacing\n // it ahead of a resolution failure keeps the actionable message the actionable one.\n // `authorizeInController` then takes the addressed id and runs the row-scoped phases only\n // when there is one.\n const isUpdate = op === CoreResourceOperation.UPDATE;\n const { id } = args as { id?: string };\n if (isUpdate && (typeof id !== 'string' || id.length === 0)) {\n throw new Error(\n `resourceWriteTool(${resourceType}, update): the \"id\" argument is required — declare it in the tool's inputSchema.`,\n );\n }\n\n // The operation the tool ADVERTISES is the resource's public, URL-bearing default; dispatch\n // that exact one rather than re-resolving through the service layer's INTERNAL-preferred\n // resolver. See `resolveDispatchableOperation` for what diverged and what it cost.\n const operation = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, op);\n // The idempotency key ARGUMENT (#747): on a variant that declares a key, the model's `idempotencyKey` argument is this\n // plane's `Idempotency-Key` header, taken out of the fields and routed to the service tier, whose request-outcome memory\n // answers the model's retry with the first result. The tool mints none: a key minted per execution would not survive the\n // model calling it again. A REQUIRED operation called without one is refused here, with the remedy, before authorizing,\n // charging or writing anything (#535 S5b-0); the tool's author advertises the argument in `inputSchema`.\n const taken = takeIdempotencyKeyToolArgument(operation, args, ({ code, field }) => new Error(\n `resourceWriteTool(${resourceType}, ${op}): ${code} — the \"${field}\" argument must be 1 to ${IDEMPOTENCY_KEY_MAX_LENGTH} printable ASCII characters.`,\n ));\n if (operation.idempotencyKey === ResourceOperationIdempotencyKeyRequirement.REQUIRED && taken.key === undefined) {\n throw new Error(\n `resourceWriteTool(${resourceType}, ${op}): the operation requires an idempotency key — pass the \"${IDEMPOTENCY_KEY_TOOL_ARGUMENT}\" `\n + 'argument, and declare it in the tool\\'s inputSchema so the model is told to send one.',\n );\n }\n const keyedOptions = taken.key !== undefined ? { idempotencyKey: taken.key } : undefined;\n const operationPath = ResourcesConfig_OperationPathUtils.extractOperationPath(operation) as ResourceConfiguration_OperationPath<any, any>;\n\n // Rebuild a scoped ExecutionContext from the CALLER's verified auth for this operation, then\n // apply the operation's own role + scope ACL against it (fail-closed) before anything is\n // written. The write runs as the user, never with an ACL bypass.\n if (!isUpdate) {\n // The seam authorizes as a COLLECTION call (no row addressed), charges the operation's own\n // budget after authorization so an unauthorized caller cannot spend an authorized one's, and\n // writes as the user — never with an ACL bypass.\n const created = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: op, contextIds, data: taken.args, options: keyedOptions });\n // Return the same JSON-safe, response-DTO-projected record the REST endpoint would, so no\n // `Date`/backend-only/secret reaches the model and the tool-loop CONTINUATION step validates.\n return toResponseSafeToolOutput(operation, created);\n }\n\n // UPDATE: the record \"id\" addresses the row AND is the authorization subject — the seam takes\n // one value for both, which is what makes authorizing a collection call while dispatching a\n // row call unrepresentable.\n const { id: _addressedRow, ...patch } = (taken.args ?? {}) as { id?: string };\n const updated = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: op, recordId: id, contextIds, data: patch, options: keyedOptions });\n return toResponseSafeToolOutput(operation, updated);\n },\n };\n}\n"]}
1
+ {"version":3,"file":"function-tools.backend.definitions.js","sourceRoot":"","sources":["../../../../src/flows-actors/models/function-tools.backend.definitions.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n type FlowsActors_PersonalDataModelTreatment,\n type FlowsActors_OutputModerationPolicy,\n CoreResourceOperation,\n ErrorType,\n RedactionType,\n ResourceOperationVariantType,\n ResourcesConfig_OperationPathUtils,\n isWildoBackendError,\n type ResourceType,\n type ResourceConfiguration_Operation,\n type ResourceConfiguration_OperationPath,\n ResourceOperationIdempotencyKeyRequirement,\n IDEMPOTENCY_KEY_MAX_LENGTH,\n IDEMPOTENCY_KEY_TOOL_ARGUMENT,\n type ResourceOperationRiskLevel,\n HumanDecision_RouteKind,\n FunctionToolAuthorityKind,\n type FunctionToolAuthorityDeclaration,\n AutonomousTurnTrigger,\n FlowsActors_InitiationKind,\n ReviewEscalationActionKind,\n reviewDeadlinesDeclarationIssues,\n type ReviewDeadlineStage,\n type ReviewDeadlinesDeclaration,\n type HumanDecision_AnswerChannels,\n type HumanDecision_StepUpRequirement,\n humanDecisionAnswerChannelsIssues,\n humanDecisionStepUpDeclarationIssues,\n humanDecisionStepUpRequirementOf,\n conversationalActorOf,\n type ActorSystem,\n AskPerson_ToolInputSchema,\n PresentRecords_ToolInputSchema,\n Resources_Filter_NumberRangeSchema,\n isResourcesFilterNumberRangeSchema,\n Resources_Filter_YearMonthRangeSchema,\n isResourcesFilterYearMonthRangeSchema,\n type PresentRecords_ToolInput,\n type PresentRecords_ToolResult,\n flowsActorsToolLabelKey,\n type FlowsActorsToolLabelSlot,\n RagRetrievalEmbeddingStatus,\n RagRetrievalSearchStatus,\n OperationDispatchPlane,\n ResourcePrimaryScope,\n ResourcesConfigOperationsDtosBuilderUtils,\n jsonParsingSchemaOf,\n} from '@wildo-ai/saas-models';\nimport { ElectronicSignature_Level } from '@wildo-ai/external-connectors-models';\nimport { takeIdempotencyKeyToolArgument } from '~wildo-backend-lib/base-classes/services/controllers/utils/idempotency-key-tool-argument.backend.utils';\n\nimport { toResponseSafeToolOutput } from '~wildo-backend-lib/base-classes/services/controllers/utils/operation-response-serializer.backend.utils';\nimport { declaredPolicySubjectKey, resolveDeclaredPolicySubject } from '~wildo-backend-lib/security/authentications/services/utils/external-turn-rate-limit.backend.utils';\nimport {\n OPERATION_DISPATCH_PLANE_FACTS,\n declaredRateLimitScopeKey,\n recordOperationRateLimitRefusal,\n} from '~wildo-backend-lib/errors/utils/declared-rate-limit-refusal.backend.utils';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { AuthorizationsBackendService } from '~wildo-backend-lib/security/authorizations/services/authorizations.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { RepositoryOptions } from '~wildo-backend-lib/base-classes/models/repositories.backend.schemas';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport { toPortableModelToolName } from '~wildo-backend-lib/flows-actors/models/model-tool-name.backend.utils';\nimport type { RateLimitBackendService } from '~wildo-backend-lib/errors/services/rate-limit.backend.service';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { ServicesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/services/services-registry-handler.backend.service';\nimport type { SocketAuthResult } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { RagRetrievalBackendService, RagRetrievalResult } from '~wildo-backend-lib/rag/services/rag-retrieval.backend.service';\nimport { observeDispatchedRecordOwners } from '~wildo-backend-lib/flows-actors/content-guardrails/tool-call-record-owners.backend';\nimport { argumentsCarryingWithheldMarkers, placeholderTolerantInputSchema, PersonalDataPlaceholderRefusal, type PersonalDataGuard, type PersonalDataPlaceholderTable, type PersonalFieldMap } from '~wildo-backend-lib/flows-actors/content-guardrails/personal-data-guard.backend.utils';\n\n/**\n * Function-Tool Contract (backend)\n * ================================\n *\n * An executable tool an AI agent can call during an invocation (the runtime\n * behind an agent's declarative `capabilities.tools.functionRefs`). Unlike the\n * shared agent/system schemas, a `FunctionTool` carries backend execution logic,\n * so it lives in `saas-backend-lib`, not `saas-models`.\n *\n * Tools are registered per-application through\n * `BackendDomainModule.flowsActors.functionTools`, indexed by `functionRef` in\n * the `FlowsActorsRegistryService`, and resolved + wired into the AI-SDK `tools`\n * parameter by `AgentsBackendService` when a streaming invocation runs. The\n * engine supplies the execution *context* (caller identity + backend services)\n * at call time; the tool itself stays a pure, reusable declaration.\n */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.tool-dispatch-obligations facet:layer:backend facet:audience:app-developer\n *\n * Backend services a tool may use at execution time (supplied by the caller).\n *\n * ⚠️ **If your tool DISPATCHES a resource operation, call `dispatchResourceOperationAsTool` — do not\n * reach for these services yourself.**\n *\n * A tool enters at the SERVICE tier, bypassing Express, so two gates that live on the HTTP\n * controller never run for it: the operation's declared `roles` ACL and its authored `rateLimit?`.\n * `dispatchResourceOperationAsTool` resolves the operation, builds the scoped execution context,\n * applies both gates in the right order and dispatches — one exported call, and the same one\n * `resourceReadTool` and `resourceWriteTool` use.\n *\n * ```ts\n * const rows = await dispatchResourceOperationAsTool({\n * ctx, resourceType: 'todos', operationIdentifier: CoreResourceOperation.LIST,\n * data: { filter: undefined, page: 1, limit: 20 }, options: { paginated: true },\n * });\n * ```\n *\n * **This prose used to name two calls a hand-written tool owed, and both were module-private (#556)\n * — so an author who read it and agreed could not discharge the obligation.** Naming ONE importable\n * call replaces that: the correct path is now also the shortest, which is the only mechanism that\n * survives an author who has not read this paragraph.\n *\n * Skipping the gates means a caller whose roles the operation REFUSES, but whose tenancy admits the\n * row, succeeds — the operation's `accessControl` simply unenforced on this plane. It is quiet:\n * tenancy still applies, so the tool returns the caller's own tenant's rows and LOOKS like it works.\n * That is right for a framework-internal caller and wrong here, where the caller is an external\n * principal naming an operation on their own authority.\n *\n * The services below remain on this interface because the seam is built from them, and because a\n * tool that dispatches NOTHING — a calculator, a formatter, a unit converter — is a legitimate shape\n * that needs neither gate.\n *\n * What you still get for free, on every tool: the repository's contextual filter in full — tenancy,\n * relationship narrowing, organization-unit narrowing, the anonymous guard and the retention hide,\n * all fail-closed — plus the whole operation pipeline of validation, enabled conditions, custom\n * implementation and hooks.\n */\nexport interface FunctionToolExecutionServices {\n resourcesRegistry: ResourcesRegistryBackendService;\n servicesRegistryHandler: ServicesRegistryHandlerBackendService;\n executionContextCreator: ExecutionContextCreatorBackendService;\n /**\n * Enforces an operation's OWN authored `rateLimit?` policy on this plane.\n *\n * Present because a tool DISPATCHES A RESOURCE OPERATION while bypassing Express, so the\n * HTTP route's counts of the declared policy never run. A\n * hand-written {@link FunctionTool} should dispatch through {@link dispatchResourceOperationAsTool},\n * which charges this service, applies the roles ACL and records a refusal (#3008). Calling\n * `checkPolicyForSubject(...)` on THIS service directly is the fallback for a tool that does not\n * dispatch through the seam: it charges the policy and records NO refusal. (The factories below wrap\n * it in the module-private `assertDeclaredOperationRateLimit`, which is not importable.)\n */\n rateLimitService: RateLimitBackendService;\n /**\n * Applies the dispatched operation's own declared `roles` ACL.\n *\n * Present because a tool enters at the SERVICE tier, and **the role gate is a CONTROLLER-tier\n * gate** — `ServicesRegistryHandlerBackendService`'s verbs apply the repository's contextual\n * filter and the whole operation pipeline, and deliberately apply no role check, because their\n * dominant population is the authentication reads that run before a role-bearing principal\n * exists. That is right for a framework-internal caller and wrong for this plane, whose caller is\n * an external principal (an A2A agent, or a user's own WebSocket) naming an operation on their\n * own authority. Without this the operation's `accessControl` was simply unenforced here: a\n * caller whose roles the operation refuses, but whose tenancy admits the row, succeeded.\n *\n * A hand-written {@link FunctionTool} that dispatches a resource operation owes the same call —\n * `authorizeInController(idOrIds, executionContext)` on THIS service. (The factories below wrap it\n * in the module-private `authorizeToolDispatch`, which is not importable from outside this file.)\n */\n authorizer: AuthorizationsBackendService;\n /**\n * Records the first refusal of each window of an operation's declared `rateLimit?` (#3008): one\n * `OPERATION_RATE_LIMIT_REFUSED` row naming the plane (an agent tool or a chat command), the operation, the subject\n * counted and the window. Optional and feature-detected: without it the policy still refuses, unrecorded. A\n * hand-written {@link FunctionTool} that dispatches through {@link dispatchResourceOperationAsTool} is charged and\n * recorded by it; one that calls `checkPolicyForSubject(...)` on its own is charged and NOT recorded.\n */\n auditLogs?: Pick<AuditLogsBackendService, 'logOperationRateLimitRefused'>;\n /**\n * Searches the application's retrieval index on the caller's own authority (#2300), for {@link retrievalTool}.\n * Optional: a plane that offers no retrieval leaves it out, and the retrieval tool then refuses with a sentence\n * rather than answering with nothing. A tool you write yourself may call it too: pass the execution context you\n * built from the caller's auth, never one with more authority.\n */\n ragRetrieval?: Pick<RagRetrievalBackendService, 'retrieve'>;\n}\n/** @wildo_source:part:end saas.backend.flows-actors.tool-dispatch-obligations */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.function-tool facet:layer:backend facet:family:flows-actors\n *\n * Execution context threaded into every tool call. Carries the CALLER's verified\n * identity (`auth`) so a tool reads/writes as the user with the user's own\n * visibility — never trusting LLM-supplied identity — plus the backend services\n * the tool may use. The engine supplies this at call time; a tool never fabricates\n * identity from the model's arguments.\n *\n * assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — a tool acts on its caller's server-verified authority, which the model can never supply.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n */\nexport interface FunctionToolExecutionContext {\n /** The authenticated caller (server-verified identity + roles). */\n auth: SocketAuthResult;\n /** Active organization scope for the call, when applicable. */\n organizationId?: string;\n /**\n * The conversational execution (the thread) this call is a turn of, when the tool runs inside\n * one. A tool that starts work elsewhere — a run, a task — stamps it onto that work so the thread\n * can list what it started; the engine supplies it and reads nothing back from it.\n */\n executionId?: string;\n /**\n * The actors system the execution runs in, when the tool runs inside one. Supplied by the engine;\n * like `executionId`, it is recorded on the agent frame the call runs in, so every audit row the tool\n * causes names the agent, the execution and the system without the tool doing anything.\n */\n systemRef?: string;\n /** Backend services the tool may use. */\n services: FunctionToolExecutionServices;\n /**\n * The human decision this call runs under, when a resumed turn is carrying out an approval (#1594).\n * The agent frame copies it onto `agentActor.decisionRef`, so the write the approved tool makes names\n * the decision that authorized it. Absent on every call no one had to approve.\n */\n decisionRef?: string;\n /**\n * #2904: the id of the approval seal of the answer `decisionRef` names (an `approvalSeals` row), set by the engine from\n * the release that wrote it, never from the model or a request. A tool that RECORDS the decision (a sign-off, an\n * acceptance) stores it beside the decider, so the record points at the signed evidence of what the person was shown\n * and answered. Absent when the answer was not sealed: a decision answered before seals existed, or a host that binds\n * no seal services. Its absence never changes whether the call may run.\n */\n decisionSealId?: string;\n /**\n * Which door opened the turn this call belongs to (#1594), read by the engine from the execution ROW —\n * at turn start and again at a decision's resume — never from the caller. It decides whether a gated call\n * may pause for a person or must be denied (`admitsDecisionSuspension`). Tools do not need to read it.\n */\n initiationKind?: FlowsActors_InitiationKind | null;\n /**\n * AUTONOMOUS turns only (#1611): what started the turn, read from the row. An `INBOUND_DELIVERY` turn\n * runs on content from outside, so the engine offers it only tools that READ or that are gated on a\n * reviewer — see {@link FunctionTool.effect}.\n */\n autonomousTrigger?: AutonomousTurnTrigger;\n /**\n * #2292: this conversation's personal-data placeholders, when its agent declares `contentGuardrails.personalData` with\n * `TOKENIZE`. Loaded by the engine from the conversation and stored again with the turn; a tool never needs it.\n */\n personalDataPlaceholders?: PersonalDataPlaceholderTable;\n /**\n * #3295: on a resumed turn, the personal-data treatment the turn paused under. The paused messages are in the form it\n * wrote, placeholders included, and only a guard under it can read them back, so the resume runs under at least this\n * however the agent's declaration or an organization's policy has moved since. Its own field rather than an entry of the\n * turn's policy frame: a frame applies only to the organizations it covers, and a call can name none, or another.\n */\n heldPersonalDataTreatment?: FlowsActors_PersonalDataModelTreatment;\n /**\n * #3364 step 3: on a resumed turn, the output moderation its replies were judged under when it paused, tightened by the\n * organizations whose records it had read. Those records stay in the paused messages, so the resume is judged under at\n * least this (`OutputModerationGuard.tighten`).\n */\n heldOutputModeration?: FlowsActors_OutputModerationPolicy;\n /**\n * #3313: told a function tool's `execute` is about to run, with the id of its call, once its arguments are final. The one\n * point that means the call ran: the SDK reports an approved call it refused to run as a `tool-error`, so an error event\n * says nothing about whether `execute` was reached. A resumed turn reads this to tell an accepted call that ran and failed\n * from one that never ran.\n */\n onFunctionToolExecuting?: (toolCallId: string) => void;\n}\n\n/**\n * What a tool can do to the world, as its author DECLARES it (#1611). Read by the engine to decide which\n * tools an agent is offered when the turn's input is untrusted — an autonomous turn started by an inbound\n * delivery, whose content came from outside and must never steer a write nobody reviews.\n */\nexport enum FunctionToolEffect {\n /** The tool only reads. Offered to every turn. */\n READ = 'read',\n /**\n * The tool may change something — a record, a message sent, money moved. The meaning of an ABSENT\n * declaration too: an unclassified tool is treated as a write, so forgetting to declare it withholds the\n * tool from untrusted turns rather than exposing it.\n */\n WRITE = 'write',\n}\n\n/**\n * A single agent-callable tool (grounding / action an agent can invoke).\n *\n * Register instances on a backend module's `flowsActors.functionTools`; reference\n * one from an agent's `capabilities.tools.functionRefs` by its `functionRef`. The\n * engine resolves each declared ref into an AI-SDK tool at invocation time and\n * calls `execute(args, context)` with the caller's {@link FunctionToolExecutionContext}\n * (so the tool acts as the user, with the user's own visibility). For reading a\n * resource, prefer the `resourceReadTool(resourceType)` factory over a hand-written\n * tool. Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // a custom tool\n * const echoTool: FunctionTool = {\n * functionRef: 'demo.echo',\n * description: 'Echo the provided text back.',\n * inputSchema: z.object({ text: z.string() }),\n * effect: FunctionToolEffect.READ,\n * // A hand-written tool says how it reaches data (#2839): this one reaches none.\n * authority: { kind: FunctionToolAuthorityKind.NO_APPLICATION_DATA, reason: 'It returns its own argument.' },\n * execute: async (args) => ({ echoed: args.text }),\n * };\n */\nexport interface FunctionTool {\n /** Stable id referenced from `agent.capabilities.tools.functionRefs`. */\n functionRef: string;\n /**\n * Natural-language description shown to the model (what the tool does + when).\n *\n * It is also the intent the labelling pipeline words the tool from for a PERSON (#2551): the title of the call's card\n * in the conversation and its working line, `flows_actors_tools.<model tool name>.{title,working}`, generated by\n * `wildo generate labels`. So say what the tool does for the person, not only how the model should call it.\n */\n description: string;\n /** Zod schema of the tool's arguments (surfaced to the model). */\n inputSchema: z.ZodTypeAny;\n /**\n * The tool's arguments as the application's RESOURCES declare them. Called ONCE, when the tool is registered (both\n * hosts register resources first; a host that does not keeps the authored schema, with a warning); what it answers\n * REPLACES `inputSchema` and `description` for every reader — the\n * model, an approval card, an approval's validation — so all of them read one schema. For a tool whose arguments ARE a\n * resource's declaration: {@link resourceReadTool} offers the filters its resource's search declares. Answering\n * `undefined` keeps the authored schema and description.\n */\n bindToResources?: (resources: FunctionToolResourceDeclarations) => Pick<FunctionTool, 'inputSchema' | 'description'> | undefined;\n /** Execute the tool with validated args under the caller's context. */\n execute: (args: any, context: FunctionToolExecutionContext) => Promise<unknown>;\n /**\n * Require a HUMAN decision before this tool runs (human-in-the-loop).\n *\n * When set, a turn that reaches this tool SUSPENDS instead of executing it: the run state is\n * persisted, the execution moves to `AWAITING_APPROVAL`, and the caller is asked to approve or\n * deny. Approving resumes the turn and runs the tool; denying resumes it and tells the model the\n * call was refused, so the agent can respond rather than silently stalling.\n *\n * Declare it on tools whose effect a person should authorise — sending money, emailing a\n * customer, deleting at scale — not on reads.\n *\n * ⚠️ Two things worth knowing before you set this:\n *\n * 1. **It requires a configured approval secret.** Approval decisions are HMAC-signed so a client\n * cannot forge one. A turn that would expose an approval-gated tool with no secret configured\n * REFUSES TO RUN rather than falling back to unsigned approvals — the tools someone bothered to\n * gate are exactly the ones where a forged approval matters most.\n * 2. **This is Wildo's declaration, not the model SDK's.** The engine translates it into the\n * SDK's call-level approval configuration. Do not reach for the SDK's own tool-level\n * `needsApproval`: it is deprecated, and approval is handled at the call level now.\n *\n * `true` means the person whose turn it is answers (an OWNER route). To route the decision to a\n * reviewer instead, declare {@link FunctionTool.humanApproval}; when both are set, `humanApproval` wins.\n */\n requiresHumanApproval?: boolean;\n /**\n * WHO must approve this tool call before it runs (#1594). Declaring it gates the tool exactly as\n * `requiresHumanApproval` does, and routes the decision:\n *\n * - `OWNER` — the person whose turn it is (what `requiresHumanApproval: true` means);\n * - `ROLE` — anyone holding `eligibleRole` in the organization the work belongs to, EXCEPT the person\n * whose turn raised it. Any holder may claim it for themselves;\n * - `ASSIGNEE` — the one person `assignee` resolves, who must hold `eligibleRole`.\n *\n * Whoever answers only decides WHETHER the call runs. It always runs under the authority of the\n * person (or machine) whose turn raised it, re-checked when the answer arrives — a reviewer's\n * wider rights never reach the agent.\n *\n * A malformed declaration (a ROLE route with no role, an ASSIGNEE route with no resolver) stops the\n * application at startup: a gate nobody can answer is refused before it can strand a turn.\n */\n humanApproval?: FunctionTool_HumanApprovalGate;\n /**\n * What this tool can do, as you declare it (#1611). `READ` tools are offered to every turn, including an\n * autonomous turn started by an inbound delivery. Anything else — `WRITE`, or no declaration at all — is\n * offered to such a turn only when it is gated on a REVIEWER (`humanApproval` with a ROLE or ASSIGNEE\n * route), because the delivery's content came from outside and must not steer a write nobody reviews.\n * `resourceReadTool` declares `READ` and `resourceWriteTool` declares `WRITE` for you; declare it on a\n * tool you write by hand.\n */\n effect?: FunctionToolEffect;\n /**\n * The resource whose fields this tool's arguments are (#1923). When a decider's decision on a call is exported as\n * evaluation data, an argument is an identifier if the tool's `inputSchema` OR this resource's own schema declares it\n * one (`.isForeignKey()`, `.isPrimaryKey()`, `IDENTITY` / `CONTACT_DETAILS` data), so a tool whose argument schema\n * restates a resource field without its decorators still has the field's meaning. `rowIdArgument` names the\n * argument that addresses the row (the row's own id). `resourceWriteTool` declares both for you.\n *\n * It also decides who sees a gated call's decision (#2734). The card shows the call's arguments, so a representative\n * (someone working in the organization through an organization relationship) is shown and may answer it only when\n * their relationship may read the row `rowIdArgument` names. Without a declared row, the decision goes to the\n * organization's own staff and to representatives of the requester's own relationship only. An edit from someone\n * answering only through a relationship may not point the row at a record their relationship cannot read, nor turn the\n * row argument into something that names no record, nor change an argument that is, or contains at any depth, a field\n * declared `.isForeignKey()` on the tool's argument schema or on any schema of this resource; and an edit the engine\n * cannot judge (this resource can no longer be read) is refused to them too. An argument that addresses a record without that declaration is not recognized, so\n * declare it. Declare `argumentsResource` on every write tool whose decisions representatives should answer.\n *\n * And it decides where a guarded agent's placeholders may go (#2292, #2848). For an agent that declares\n * `contentGuardrails.personalData`, the arguments of every tool that can change something are checked before it runs:\n * a `⟦withheld:…⟧` marker or a placeholder the conversation did not issue is refused whatever the tool declares, and\n * an issued placeholder is put back only into a field this resource declares to hold data of the same kind. A write\n * tool without `argumentsResource` (and whose result is not `RECORDS_OF_RESOURCE`) accepts no placeholder at all.\n */\n argumentsResource?: FunctionTool_ArgumentsResource;\n /**\n * The argument that names a FILE the person approves (#2904): a generated document, an agent's output file, a report to\n * send. Declare it on an approval-gated tool whose call is about a file, so that what the person approves is the file's\n * BYTES and not merely its id:\n *\n * - the decision's card binds the file by its content hash (hashed now when the file has none), so an answer given on a\n * card shown before the file's recorded hash changed is refused as stale;\n * - the approval's seal commits to `H(salt ‖ contentSha256)` and attests the file, which is then frozen while the seal\n * exists (its bytes are not removed or replaced on request), and a verifier given the file's bytes reports a file\n * changed since the approval;\n * - an approver may not edit this argument: approving another file than the one shown is not an approval of it.\n *\n * A file the engine cannot hash (a remote reference whose vendor keeps the bytes, a deleted or missing file, a file of\n * another organization) is shown and sealed as NOT bound, never bound to an empty hash.\n *\n * Registration refuses it on a tool that is not approval-gated, on a question tool, and when the tool's argument schema\n * has no top-level string argument of that name. A tool without it is unaffected.\n */\n deliverableFileArgument?: string;\n /**\n * The fields of the row the call acts on that the approval COVERS (#2914): the record's SEALED FIELD SET. Declare it\n * on an approval-gated tool whose approval is a statement about a record's values (a month's figures signed off, an\n * invoice's amounts approved), so that whether the approval still holds can be answered later:\n *\n * - the decision's card shows these values of the row named by `argumentsResource.rowIdArgument`, read as the system\n * when the card is built, so the person approves what they read; a card read before one of them changed is refused\n * as stale;\n * - the approval's seal commits to them inside its presentation, and the currency check\n * (`approvalSealSubjectCurrencyOf`, the operator door `POST /internal/admin/approval-seals/currency`, and\n * `wildo seal verify --subject-record`) compares them with the record as it is: CURRENT right after the approval,\n * NO_LONGER_CURRENT once one of them changes.\n *\n * Name only what the approval is ABOUT. Never a lifecycle or approval field (a status, `updatedAt`, the column the\n * approved call writes the seal's id or the signer into): the approved call's own write would otherwise make its own\n * seal look stale. A row of another organization than the decision's, or one that cannot be read, is shown and sealed\n * with no record values, and so is an answer given on a chat card: no notice card shows the row, so its SENT seal\n * claims none of it (its currency reads NO_SEALED_FIELD_SET).\n *\n * Registration refuses it on a tool that is not approval-gated, on a question tool, without\n * `argumentsResource.rowIdArgument`, and when it names no field, a field twice, or a field the resource's main schema\n * does not declare (checked when the resource is registered).\n */\n sealedRecordFields?: readonly string[];\n /**\n * An approval of this tool on a row REPLACES the latest earlier approval of this tool on the same row (#2914): its seal\n * names that earlier seal as the one it supersedes, as a decision answered again supersedes its own earlier seal. For a\n * decision that is taken again on the same record after the record was reopened (a month signed off, reopened and\n * signed off again): the two are different decisions, and without this the second seal names no predecessor, so a\n * verifier sees two approvals of one record and nothing saying which one stands.\n *\n * Only the latest seal of the same source, the same record (`argumentsResource.rowIdArgument`) and the same tool is\n * superseded, never an approval made through another tool on that row; a decision answered again still supersedes its\n * own earlier answer first. Requires an approval gate and `argumentsResource.rowIdArgument`.\n */\n approvalReplacesEarlierApprovalOfRow?: boolean;\n /**\n * The electronic signature the file deliverable needs once the person approved it (#2293): after the approval's seal is\n * SEALED, the engine sends the approved file (`deliverableFileArgument`, bound by its hash) to the vendor selected for\n * `ELECTRONIC_SIGNATURE`, for `signers` to sign at `requiredLevel`, and records a `signatureRequests` row. Only a\n * validated signed document makes that request SIGNED. Opt-in per deliverable: a tool without it is unaffected.\n *\n * Requires `deliverableFileArgument`, an approval gate, and the `ELECTRONIC_SIGNATURE` capability enabled with a\n * provider that applies `requiredLevel`: the application refuses to start otherwise, so a requirement nothing could meet\n * is found before the first approval rather than after it.\n *\n * @example\n * electronicSignature: { requiredLevel: ElectronicSignature_Level.ADVANCED, signers: [FunctionTool_SignerSource.APPROVER] },\n */\n electronicSignature?: FunctionTool_ElectronicSignatureRequirement;\n /**\n * The tool IS a question to the person whose turn it is (#2720). Set by {@link askPersonTool}; do not set it on a\n * tool you write by hand.\n *\n * Its approval is not an approval: the turn pauses on the call as on any gated tool, but the person is shown the\n * call's QUESTIONS through a form and answers them, and the answer becomes the tool's result. Such a pause is settled\n * by an answer carrying the person's values, or by declining, and never by a bare approve, which would run the tool\n * on whatever answers the model wrote. It must be gated on the OWNER route: only the person in the conversation\n * answers it (a question to a reviewer belongs to an actor system's run).\n */\n asksThePerson?: boolean;\n /**\n * For a question tool (`asksThePerson`): whether the engine composes a form for its questions (#2720 D). `false` asks\n * them through the request's default form, exactly as written: a text box, the options, a yes or no. For a host whose\n * questions invite free answers (\"none\", \"contact us\", \"not decided yet\") that a typed control would refuse, such as\n * the creation workbench's interview (#2731). Absent: composed.\n */\n composesQuestionForm?: boolean;\n /**\n * For a question tool: what the agent is told when the person declines, in place of `ASK_PERSON_DECLINED_REASON`.\n * A host whose own rules say what to do without an answer (propose answers for the person to review, say) names\n * them here, so the agent is not told two different things.\n */\n questionDeclinedReason?: string;\n /**\n * The tool SHOWS its person records: the conversation draws a successful call as the records' summary cards, read\n * back from the call's input, rather than as a tool card. Set by {@link presentRecordsTool}; do not set it on a tool\n * you write by hand, whose input would not read back as records.\n */\n presentsRecords?: boolean;\n /**\n * The resources the tool SEARCHES through the retrieval index (#2300). Set by {@link retrievalTool}; startup refuses an\n * application whose retrieval tool names a resource that declares no `.ragSource()` field, which would otherwise\n * search nothing and answer as if nothing matched.\n */\n retrievalSources?: readonly ResourceType[];\n /**\n * What this tool's RESULT carries, so an agent declaring `contentGuardrails.personalData` (#2292) can treat its personal\n * fields before the model reads them. Declare it on every tool you write by hand: startup refuses a guarded agent\n * offered a tool that does not say, because an undeclared result could carry anything. An organization's policy can put\n * ANY language-model agent under a treatment (#2292 R8); an undeclared tool's result then reaches that agent's model\n * withheld whole, and startup warns about every such tool.\n *\n * - `{ kind: RECORDS_OF_RESOURCE, resourceType }` — records of that resource: a record, or `{ data: [records] }`. Their\n * personal fields are treated; for a tool that WRITES them, a placeholder in its arguments is put back too (only into\n * a field of the same kind). A row of an organization-owned resource is treated under its organization's agent\n * policy too (#2877), so the engine must know whose row it is (#3369). It does when the row keeps its\n * `organizationId`, and for a `PRINCIPAL_RESOURCE_OPERATION` tool whatever the row keeps, because each dispatch\n * records the owners of the rows it returned (as long as the operations it dispatches return rows naming their\n * organization: a custom operation's answer that names none leaves the call's rows to the strictest policy). A tool reaching its rows any other way declares\n * `rowsNameTheirOrganization: true` once every row it returns carries `organizationId`; without it, startup names the\n * tool, and a row naming no organization read by an agent acting in none is treated under the strictest policy.\n * - `{ kind: NOT_FROM_RECORDS, reason }` — nothing the engine moved from a record (an id list, a computed total, the\n * answer a person chose to give). Say why: the reason is what a reviewer reads.\n * - `{ kind: TREATED_BY_TOOL, treat }` — the tool knows its own shape and treats it (the engine's retrieval tool).\n *\n * `resourceReadTool`, `resourceWriteTool`, `presentRecordsTool`, `askPersonTool` and `retrievalTool` declare it for you.\n * The model is sent the treated result; the person, the conversation's tool trace and the cards keep the real values.\n */\n personalDataOutput?: FunctionTool_PersonalDataOutput;\n /**\n * How this tool reaches the application's data, and so on whose authority (#2839). The engine closes every tool over\n * its caller's server-verified `auth`; what it does with that inside `execute` is the tool's own code, which nothing\n * can check, so it is declared here:\n *\n * - `{ kind: PRINCIPAL_RESOURCE_OPERATION }` — every data access is {@link dispatchResourceOperationAsTool} (the\n * operation's roles, the tenancy filter and its rate limit, for the caller);\n * - `{ kind: PRINCIPAL_SCOPED_SERVICE, reason }` — a service given a context built from the caller's `auth`;\n * - `{ kind: NO_APPLICATION_DATA, reason }` — the tool touches no application data;\n * - `{ kind: SYSTEM_AUTHORITY, reason }` — it reaches data through a `*AsSystem` door, beyond the caller's own reach.\n *\n * `resourceReadTool`, `resourceWriteTool`, `presentRecordsTool`, `askPersonTool` and `retrievalTool` declare it for you.\n * Declare it on every tool you write by hand: the evidence an application's `WILDO.AI.AGENT_AUTHORITY_CONFINEMENT`\n * claim rests on lists every tool with its declaration, and reports one that declares nothing. It is never refused at\n * registration.\n */\n authority?: FunctionToolAuthorityDeclaration;\n /**\n * #2292: the result is the words of the PERSON the agent works for — the answer they gave to its question — and not\n * content somebody else wrote. An agent's prompt-injection screening (`contentGuardrails.promptInjection`) does not\n * screen it: the person's own words, on their own authority, are not a third party's injection. Set by\n * {@link askPersonTool}. It opts a result out of a security control, so registration refuses it on any tool that is not\n * a question tool (`asksThePerson`).\n */\n returnsThePersonsOwnWords?: true;\n}\n\n/** How a tool's result relates to personal data. See {@link FunctionTool.personalDataOutput}. */\nexport enum FunctionToolPersonalDataOutputKind {\n /** Records of one resource: a record, or `{ data: [records] }`. */\n RECORDS_OF_RESOURCE = 'records_of_resource',\n /** Nothing the engine moved from a record. */\n NOT_FROM_RECORDS = 'not_from_records',\n /** The tool treats its own result. */\n TREATED_BY_TOOL = 'treated_by_tool',\n}\n\n/** See {@link FunctionTool.personalDataOutput}. */\nexport type FunctionTool_PersonalDataOutput =\n | {\n readonly kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE;\n readonly resourceType: ResourceType;\n /**\n * #3369: every row this tool returns carries its resource's `organizationId` (the organization row its own `_id`).\n * For a tool that does not reach its rows through `dispatchResourceOperationAsTool`, whose owners the engine\n * therefore cannot observe. Checked on every row: one that still names no organization is treated under the\n * strictest policy, and counted on the call's operation record.\n */\n readonly rowsNameTheirOrganization?: true;\n }\n | { readonly kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS; readonly reason: string }\n | {\n readonly kind: FunctionToolPersonalDataOutputKind.TREATED_BY_TOOL;\n /** The result as the model may read it, every personal value replaced through `guard`. */\n readonly treat: (output: unknown, guard: PersonalDataGuard) => unknown;\n };\n\n/** The resource a tool's arguments describe. See {@link FunctionTool.argumentsResource}. */\nexport interface FunctionTool_ArgumentsResource {\n resourceType: ResourceType;\n /** The argument holding the id of the row the call acts on, when there is one. */\n rowIdArgument?: string;\n}\n\n/**\n * How an approval-gated tool routes its decision. See {@link FunctionTool.humanApproval}.\n */\nexport interface FunctionTool_HumanApprovalGate {\n route: HumanDecision_RouteKind;\n /**\n * How risky the CALL this gate holds is, in the vocabulary a resource operation declares its own risk in (#2526).\n * Every surface that answers the decision reads it: HIGH and CRITICAL put Approve behind a confirmation, and the\n * inbox can sort by it. Absent means no badge and no confirmation, never a default: a severity nobody declared would\n * be a claim nobody made.\n *\n * Declare what the operation the tool performs declares. A tool that deletes through an operation declared HIGH\n * declares HIGH here, so the person approving the call is warned exactly as one deleting the record by hand is.\n *\n * It is declared rather than derived because a hand-written tool names no operation: its `execute` may run several,\n * or none, and `argumentsResource` names the resource its arguments describe, not the verb. A `resourceWriteTool`\n * does know its operation, and still declares the risk here (pass `humanApproval: { route, riskLevel }`): the\n * boolean `requiresHumanApproval` carries no risk. The actor system's own `riskLevel` says how much an assistant may\n * be trusted overall, which is a different statement from how much this one call can do, so it is never shown in\n * place of this.\n */\n riskLevel?: ResourceOperationRiskLevel;\n /**\n * ROLE and ASSIGNEE: the role every answerer must hold. For ROLE it is the role the decision is\n * routed to. It is also the floor for anyone the decision is later reassigned, escalated or claimed\n * to: a move can never hand it to someone this gate would not have admitted.\n */\n eligibleRole?: string;\n /**\n * ROLE and ASSIGNEE: the professional qualifications every answerer must ALSO hold (#2967), kinds the application\n * declares in `professionalQualificationKinds`. Read when they act: a qualification verified, within its validity, and\n * recorded by the organization they decide for here — their own organization for one of its own members, the\n * representing organization for someone deciding through a relationship. A floor like `eligibleRole`: a reassignment,\n * an escalation or a claim can never hand the decision to someone without them.\n *\n * Use it when the decision must be taken by a person who is qualified, not merely one who holds a role: a chartered\n * accountant posting an adjustment, a licensed engineer signing off a design. Startup refuses a kind the application\n * does not declare, and an OWNER route (its answerer is the person whose turn it is, who is not vetted).\n *\n * ```ts\n * humanApproval: { route: HumanDecision_RouteKind.ROLE, eligibleRole: 'accountant', requiredQualificationKinds: ['chartered-accountant'] }\n * ```\n */\n requiredQualificationKinds?: readonly string[];\n /**\n * Whether the answer must carry a fresh step-up proof bound to THIS decision (#2923), as an operation approval's\n * `requiresApproval.requiresStepUpAuthentication` does. The person re-proves a factor (`POST /auth/reauth` with a\n * `decisionBinding` naming the decision and the presentation they answer) and answers from the decision inbox with it\n * in `X-Reauth-Token`. A socket or chat answer carries no proof, so it is refused (`decision_step_up_required`).\n *\n * Use it when approving the call commits the person to something they must be present for: releasing a payment,\n * signing off a filing. Applies to an agent's question (`askPersonTool`) the same way.\n */\n requiresStepUpAuthentication?: boolean;\n /**\n * What that step-up must ALSO be (#2923), with `requiresStepUpAuthentication: true`; startup refuses it without:\n * `maximumAgeSeconds` (at most 300) since the factor was proven, and a `minimumAssurance` of `reproven` (any step-up\n * factor), `possession` (TOTP or a passkey) or `phishing_resistant` (a passkey). The approvers' user types must allow\n * that factor as a step-up method. The factor and the instant it was proven are recorded on the decision and its\n * approval seal (`decider.stepUpMethod`, `decider.stepUpAt`).\n *\n * ```ts\n * humanApproval: {\n * route: HumanDecision_RouteKind.ROLE, eligibleRole: 'treasurer',\n * requiresStepUpAuthentication: true,\n * stepUp: { maximumAgeSeconds: 120, minimumAssurance: HumanDecision_StepUpAssurance.PHISHING_RESISTANT },\n * }\n * ```\n */\n stepUp?: HumanDecision_StepUpRequirement;\n /**\n * The channels that may answer the call (#2923): `web_session` (the application), `chat` (a chat card),\n * `api_client` (a client the person delegated to). Absent: every channel the other requirements allow. A tool approval\n * is decided in person, so `api_client` never answers one whatever this says; `chat` is refused beside a step-up, which\n * a chat answer cannot carry. A chat card for a call it may not answer links to it in the application.\n */\n answerChannels?: HumanDecision_AnswerChannels;\n /**\n * ASSIGNEE only: resolves the ONE person to route to, when the call pauses, from its arguments and\n * context (for example, the record's account manager). Returning `undefined`, or a person without\n * `eligibleRole`, refuses the pause and the call is denied — a decision nobody may answer is never\n * created.\n */\n assignee?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n /**\n * Where ESCALATE moves the decision when the person escalating names nobody. Resolves one person,\n * who is vetted against `eligibleRole` like any other target. Without it, an escalation must name\n * its target; there is no default escalation to administrators.\n */\n escalateTo?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n /**\n * When the decision should be taken, answered, and given up on (#1628). Optional: a gate declaring\n * nothing still gets a 24-hour lapse and two reminders — at half of it nobody has taken the decision,\n * at three quarters nobody has answered — sent to the people who may answer it.\n *\n * A deadline changes who is ASKED and who is TOLD, never what is decided. Missing one never approves\n * and never rejects; only the lapse ends the decision, as LAPSED, which is never counted as a refusal.\n *\n * ```ts\n * deadlines: {\n * lapseAfter: 'PT48H', // ISO-8601; always elapsed time\n * claim: { at: 'PT4H', basis: ReviewClockBasis.CALENDAR }, // counted in the application's reviewCalendar\n * decision: { at: { fractionOfLapse: 0.75 }, warnBefore: 'PT2H' },\n * rules: [\n * { stage: ReviewDeadlineStage.DECISION_WARNING, action: ReviewEscalationActionKind.NOTIFY },\n * { stage: ReviewDeadlineStage.DECISION_MISSED, action: ReviewEscalationActionKind.REASSIGN, target: resolveTeamLead },\n * ],\n * pauseStates: ['awaiting-requester-information'],\n * }\n * ```\n *\n * A declaration that could never do what it says stops the application at startup: a CALENDAR clock in\n * an application with no `reviewCalendar`, a target at or after the lapse, a REASSIGN rule with no\n * target or on an OWNER gate.\n */\n deadlines?: FunctionTool_HumanApprovalDeadlines;\n /**\n * What a person's DENIAL does to the record the call was about (#3015). A denied call does not run `execute`,\n * so without this a denial changes nothing: an agent's proposal stays proposed, and the application needs a\n * second, unsealed act to record the rejection. Declared here, the denial IS the rejection. It runs once the\n * sealed REJECTED decision has committed, like `execute` once an approval has, with the same context: the\n * requester's authority and the decision's `decisionRef`, which the effect reads back from the engine's record of\n * the decision rather than trusting.\n *\n * It runs only for a person's REJECTED answer, never for a lapse, a withdrawal, or the engine's own denial of a\n * call nobody can answer (nobody decided). It receives the arguments the model proposed (the denied call), and runs\n * in the agent's actor frame, so the rows it writes name the agent, the tool and the decision. Its failure never\n * undoes the decision: the denial stays sealed, the failure is logged, and the resumed turn is told that the record\n * did not move.\n *\n * The usual effect is a server-owned transition (an `INTERNAL_CALL` operation) on the row the call named, given\n * `ctx.decisionRef` and `ctx.executionId` so it can read the decision back before moving anything. The decision is\n * on the conversation's execution row, in whichever of `userFlowActorExecutions`, `organizationFlowActorExecutions`\n * and `applicationFlowActorExecutions` holds it: read each with `readAsSystem` on\n * `{ executionId, lastResolvedDecisionRef: decisionRef }` (the fields are backend-only, and a NOT_FOUND means the\n * next variant). The transition refuses unless `decisionOutcome` is `REJECTED`, `decidedByUserId` is set, and\n * `decisionToolName` equals `modelToolNameForFunctionRef(<this tool's functionRef>)`: the name the model saw, in\n * which a dot becomes `_`, never the dotted functionRef itself.\n *\n * ```ts\n * humanApproval: {\n * route: HumanDecision_RouteKind.ROLE,\n * eligibleRole: 'accountant',\n * onDenied: async (args, ctx) => {\n * const { proposalId } = PostProposal_InputSchema.parse(args); // the arguments the model proposed\n * const { resourcesRegistry, executionContextCreator, servicesRegistryHandler, authorizer } = ctx.services;\n * const contextIds = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n * const contextFor = (operation: string, path = resourcesRegistry.getServiceOperationPathDefault('proposals', operation)) =>\n * executionContextCreator.buildContextFromSocketAuth(ctx.auth, resourcesRegistry.getOperationFromPath(path), contextIds);\n * // An INTERNAL_CALL operation has no role gate of its own: the requester must hold the row's own UPDATE.\n * await authorizer.authorizeInController(proposalId, await contextFor(CoreResourceOperation.UPDATE,\n * resourcesRegistry.getOperationPathDefault('proposals', CoreResourceOperation.UPDATE)));\n * await servicesRegistryHandler.executeCustomOperation('proposals', 'record_denial', await contextFor('record_denial'),\n * proposalId, { decisionRef: ctx.decisionRef, executionId: ctx.executionId });\n * },\n * }\n * ```\n *\n * assurance-control: WILDO.AI.HUMAN_OVERSIGHT — a person's refusal of an agent's proposal takes effect on the record it refused, as the outcome of the sealed decision.\n */\n onDenied?: (args: unknown, context: FunctionToolExecutionContext) => Promise<void>;\n}\n\n/**\n * A gate's deadline declaration: the data {@link ReviewDeadlinesDeclaration} with a REASSIGN rule's\n * target resolver beside it. See {@link FunctionTool_HumanApprovalGate.deadlines}.\n */\nexport interface FunctionTool_HumanApprovalDeadlines extends Omit<ReviewDeadlinesDeclaration, 'rules'> {\n rules?: FunctionTool_ReviewEscalationRule[];\n}\n\n/** What one deadline stage does. Declared rules replace the default reminders. */\nexport interface FunctionTool_ReviewEscalationRule {\n stage: ReviewDeadlineStage;\n action: ReviewEscalationActionKind;\n /**\n * REASSIGN only, and required there: resolves the one person the decision moves to, from the call's\n * arguments, under the REQUESTER's authority as it stands when the stage fires. That person must be able\n * to answer it (hold the gate's `eligibleRole`, and not be the requester); if not, or if nobody resolves,\n * the rule notifies instead and the refusal is recorded. When several REASSIGN rules fire at one stage,\n * the first declared wins.\n */\n target?: (args: unknown, context: FunctionToolExecutionContext) => Promise<string | undefined>;\n}\n\n/**\n * Whether a tool may be OFFERED to a turn, given where the turn's input came from (#1611). The one place\n * this is decided; the agents service asks it for every declared tool.\n *\n * Every tool is offered to an ordinary turn. An autonomous turn started by an inbound delivery is offered\n * only a tool that READS, or one gated on a REVIEWER — so a write that content from outside asks for is\n * either impossible or seen by a person first. An OWNER-gated tool is not offered there either: a machine\n * turn has no owner to ask, so the call could only ever be denied.\n *\n * A tool that SHOWS records (`presentsRecords`) is offered only to a turn a person watches in a conversation the\n * application draws. An A2A caller receives the reply's text and no tool calls, and an autonomous turn has nobody\n * watching: offered there, the agent would show cards nobody sees and leave them out of the text the reader does get.\n */\n// assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — a turn started by content from outside is offered no write a reviewer does not see first.\nexport function isFunctionToolOfferedToTurn(\n tool: Pick<FunctionTool, 'functionRef' | 'requiresHumanApproval' | 'humanApproval' | 'effect' | 'presentsRecords'>,\n autonomousTrigger: AutonomousTurnTrigger | undefined,\n initiationKind?: FlowsActors_InitiationKind | null,\n): boolean {\n if (tool.presentsRecords === true && (autonomousTrigger !== undefined || !turnIsDrawnForAPerson(initiationKind))) return false;\n if (autonomousTrigger !== AutonomousTurnTrigger.INBOUND_DELIVERY) return true;\n if (tool.effect === FunctionToolEffect.READ) return true;\n const route = resolveFunctionToolApprovalGate(tool)?.route;\n return route === HumanDecision_RouteKind.ROLE || route === HumanDecision_RouteKind.ASSIGNEE;\n}\n\n/**\n * The resource whose personal fields a guarded agent's placeholder may be put back into, in this tool's ARGUMENTS\n * (#2848): the resource the arguments describe (`argumentsResource`), else the resource of the records the tool returns\n * (`personalDataOutput: RECORDS_OF_RESOURCE`). `undefined` when the tool names neither: no argument may then carry a\n * placeholder, because nothing says which field of which resource it would land in.\n *\n * Keyed on the ARGUMENTS first because the result declaration says what the model is SENT, not what the tool WRITES: a\n * write whose result is only ids is `NOT_FROM_RECORDS`, and its arguments must still be checked.\n */\nexport function personalDataArgumentsResourceOf(tool: Pick<FunctionTool, 'argumentsResource' | 'personalDataOutput'>): ResourceType | undefined {\n if (tool.argumentsResource !== undefined) return tool.argumentsResource.resourceType;\n return tool.personalDataOutput?.kind === FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE ? tool.personalDataOutput.resourceType : undefined;\n}\n\n/**\n * Whether a guarded agent's arguments to this tool are checked and re-identified before it runs (#2848): every tool that\n * can change something (an undeclared `effect` counts as a write), and every tool that names a resource for its\n * arguments or its records. Only a pure read naming no resource passes its arguments as the model wrote them, since\n * nothing it does stores them.\n *\n * Until #2848 the check was keyed on the RESULT declaration alone, so a write tool declaring `NOT_FROM_RECORDS` stored a\n * `⟦withheld:…⟧` marker or a placeholder exactly as the model wrote it.\n */\n// assurance-control: WILDO.PRIVACY.DATA_MINIMIZATION — a guarded agent's write never stores a placeholder or a withheld marker, whatever its tool declares about its result.\nexport function functionToolArgumentsAreGuarded(tool: Pick<FunctionTool, 'effect' | 'argumentsResource' | 'personalDataOutput'>): boolean {\n return tool.effect !== FunctionToolEffect.READ || personalDataArgumentsResourceOf(tool) !== undefined;\n}\n\n/** One date-text form per schema: the SDK and the decision door ask for it on every call. See {@link toolCallSchemaOf}. */\nconst TOOL_CALL_SCHEMAS = new WeakMap<z.ZodTypeAny, z.ZodTypeAny>();\n\n/**\n * A parse output with every `Date` put back to the text (or epoch number) it was read from in `raw`, at the same place; a\n * `Date` with no such counterpart (one a transform or a default made) as its RFC 3339 text. Everything else as parsed.\n */\nfunction withDateText(parsed: unknown, raw: unknown): unknown {\n if (parsed instanceof Date) return typeof raw === 'string' || typeof raw === 'number' ? raw : parsed.toISOString();\n if (Array.isArray(parsed)) return parsed.map((item, index) => withDateText(item, Array.isArray(raw) ? raw[index] : undefined));\n if (parsed !== null && typeof parsed === 'object' && Object.getPrototypeOf(parsed) === Object.prototype) {\n const rawFields = raw !== null && typeof raw === 'object' && !Array.isArray(raw) ? raw as Record<string, unknown> : {};\n return Object.fromEntries(Object.entries(parsed).map(([key, value]) => [key, withDateText(value, Object.hasOwn(rawFields, key) ? rawFields[key] : undefined)]));\n }\n return parsed;\n}\n\n/**\n * A tool's arguments as the SDK holds a call (#3489): validated by the schema's JSON form, every check, refinement and\n * transform included, but with each DATE kept as the text it was written in rather than read into a `Date`.\n *\n * ## Why the SDK must never hold a `Date`\n *\n * The SDK treats a call's input as JSON data, and three of its mechanisms break on anything else:\n * - an approval-gated call is paused and stored as JSON, and on approval the SDK requires that parsing the call again\n * yields the stored input (`isDeepEqualData`). A `Date` comes back from storage as its text, so a date argument never\n * compared equal and the call could never be approved;\n * - the approval signature hashes the input with `canonicalJSON`, which writes a `Date` as `{}`: it covered no date's value;\n * - a person's edit is stored as written, and a date parsed to a `Date` never equals the person's text either.\n * spec-cite: N/A — read from the `ai@7.0.142` source (`generate-text/validate-tool-approvals.ts`, `util/is-deep-equal-data.ts`,\n * `util/canonical-hash.ts`), which documents none of it.\n *\n * So the text stays text up to `execute`, where {@link argumentsAToolExecutesWith} reads the dates (a value walk, no second\n * parse). The JSON Schema the model is told is the JSON form's own (a date is `string`, `date-time`): zod's pipe\n * processor is mirrored, since the wrapper's own input side is `any`.\n *\n * Rejected: restoring the stored call's `Date`s at the resume. It made the stored input equal again, but left the\n * signature blind to dates and an edit's text unequal; and the issue's other direction, refusing a gated tool that\n * declares `z.date()`, would forbid what the framework teaches applications to declare.\n */\nexport function toolCallSchemaOf(schema: z.ZodTypeAny): z.ZodTypeAny {\n const known = TOOL_CALL_SCHEMAS.get(schema);\n if (known) return known;\n const jsonForm = jsonParsingSchemaOf(schema);\n const callForm = z.any().transform(async (raw, ctx) => {\n const parsed = await jsonForm.safeParseAsync(raw);\n if (!parsed.success) {\n for (const issue of parsed.error.issues) ctx.addIssue({ ...issue } as never);\n return z.NEVER;\n }\n return withDateText(parsed.data, raw);\n });\n callForm._zod.processJSONSchema = (ctx, _json, params) => {\n z.core.process(jsonForm, ctx as never, params as never);\n (ctx as unknown as { seen: Map<z.ZodTypeAny, { ref?: z.ZodTypeAny }> }).seen.get(callForm)!.ref = jsonForm;\n };\n TOOL_CALL_SCHEMAS.set(schema, callForm);\n return callForm;\n}\n\n/**\n * The schema the SDK validates this tool's calls against, which is also the one it revalidates an approved call with\n * (#3295): the tool's own, or under `TOKENIZE` the form whose personal fields also accept a placeholder, since a personal\n * value reaches the SDK as one. The ONE answer: the agent service hands it to the SDK and the decision door rehearses with\n * it, so the two read one schema.\n *\n * In its call form ({@link toolCallSchemaOf}): validated as JSON (#3478), a date's text kept (#3489). A model writes a tool\n * call as JSON, so a `z.date()` argument arrives as an RFC 3339 string; it is checked here, told to the model as `string`\n * `date-time`, and read into a `Date` only for `execute`.\n */\nexport function sdkInputSchemaOfFunctionTool(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n): z.ZodTypeAny {\n const argumentsResource = guard !== undefined && functionToolArgumentsAreGuarded(tool) ? personalDataArgumentsResourceOf(tool) : undefined;\n return toolCallSchemaOf(guard?.treatment === RedactionType.TOKENIZE && argumentsResource !== undefined\n ? placeholderTolerantInputSchema(tool.inputSchema, guard.personalFieldsOf(argumentsResource))\n : tool.inputSchema);\n}\n\n/**\n * The target fields of a guarded write whose tool names no resource for its arguments (#2848): none. Every issued\n * placeholder is then refused (\"that field does not hold data of the same kind\"), as is every withheld marker and every\n * placeholder the conversation did not issue, so the write can store only values the model actually wrote.\n */\nconst NO_PERSONAL_ARGUMENT_FIELDS: PersonalFieldMap = new Map();\n\n/**\n * What a tool's `execute` receives for the arguments the SDK hands it (#2292, #3295): under a guard, a placeholder is put\n * back (only into a field of the same kind) and the result held to the tool's own schema, which the placeholder-tolerant\n * one the model saw was not. Throws what the run would throw: a `PersonalDataPlaceholderRefusal` for a marker or a\n * placeholder that cannot be put back, a schema error for a value the tool refuses.\n *\n * The ONE body of that step: `execute` runs it, and the decision door rehearses it before a decision settles, so a call\n * cannot be recorded as accepted on an answer the run would refuse.\n */\nexport async function argumentsAToolRunsWith(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n args: unknown,\n): Promise<unknown> {\n if (!functionToolArgumentsAreGuarded(tool)) return args;\n if (guard === undefined) {\n // #2877: an unguarded call can still hold a withheld marker in its messages: a row an organization outside the call's\n // scope owns was withheld from its model (`treatRecordsResultByOwner`), and a resume after an approval pause runs with\n // no guard of that call. A marker stands for a value nobody may store, so it is refused here whatever the call, and the\n // decision door rehearses the same refusal. Nothing else changes for an unguarded call: no placeholder is put back and\n // the arguments are not parsed again.\n const carrying = argumentsCarryingWithheldMarkers(args);\n if (carrying.length > 0) {\n throw new PersonalDataPlaceholderRefusal(`${carrying.map((name) => `'${name}'`).join(', ')} carries a value you were not shown (⟦withheld:…⟧). Write a value you know, or leave the field out.`);\n }\n return args;\n }\n // Asynchronously, as the SDK validates: a tool may declare an async refinement, and `parse` would refuse every value of it.\n // The tool's own schema in its call form (#3478, #3489): a date is checked and kept as its text, as the SDK holds it, so\n // the decision door compares what a person read with what runs; `execute` reads it (`argumentsAToolExecutesWith`).\n return toolCallSchemaOf(tool.inputSchema).parseAsync(guard.reidentifyArguments(args, argumentFieldsOf(tool, guard)));\n}\n\n/**\n * What a tool's `execute` is called with (#3489): {@link argumentsAToolRunsWith}, with each date the tool's schema declares\n * read into a `Date`. The SDK holds a date as its text ({@link toolCallSchemaOf}), so this is where the tool gets the\n * `Date` its `z.date()` promises. A value walk on the schema's output side, never a second parse: the arguments are\n * already validated, and a transform must not run twice.\n */\nexport async function argumentsAToolExecutesWith(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n args: unknown,\n): Promise<unknown> {\n return ResourcesConfigOperationsDtosBuilderUtils.restoreStoredDates(await argumentsAToolRunsWith(tool, guard, args), tool.inputSchema);\n}\n\nfunction argumentFieldsOf(tool: Pick<FunctionTool, 'argumentsResource' | 'personalDataOutput'>, guard: PersonalDataGuard): PersonalFieldMap {\n const argumentsResource = personalDataArgumentsResourceOf(tool);\n return argumentsResource === undefined ? NO_PERSONAL_ARGUMENT_FIELDS : guard.personalFieldsOf(argumentsResource);\n}\n\n/**\n * #3295: {@link argumentsAToolRunsWith} rehearsed for the decision door, which must say why rather than throw: what\n * `execute` would receive (`ran`) beside the same arguments before its parse (`readAs`, the values a person reads), or the\n * arguments that stop it, by name. A value that cannot be put back is named alone, by asking the guard field by field; a\n * refusal it cannot place names every argument.\n */\nexport async function rehearsedToolArguments(\n tool: Pick<FunctionTool, 'inputSchema' | 'effect' | 'argumentsResource' | 'personalDataOutput'>,\n guard: PersonalDataGuard | undefined,\n executedCopy: Record<string, unknown>,\n): Promise<{ ran: unknown; readAs: unknown } | { refusedArguments: string[] }> {\n const guarded = guard !== undefined && functionToolArgumentsAreGuarded(tool) ? guard : undefined;\n try {\n return {\n ran: await argumentsAToolRunsWith(tool, guard, executedCopy),\n readAs: guarded ? guarded.reidentifyArguments(executedCopy, argumentFieldsOf(tool, guarded)) : executedCopy,\n };\n } catch {\n const unreadable = guarded === undefined ? argumentsCarryingWithheldMarkers(executedCopy) : Object.entries(executedCopy).filter(([name, value]) => {\n try {\n guarded.reidentifyArguments({ [name]: value }, argumentFieldsOf(tool, guarded));\n return false;\n } catch {\n return true;\n }\n }).map(([name]) => name);\n return { refusedArguments: (unreadable.length > 0 ? unreadable : Object.keys(executedCopy)).sort() };\n }\n}\n\n/**\n * Whether a turn's conversation is drawn for a person by the application: a turn over the application's own socket.\n * A turn that records no door predates the door's recording and was a socket turn. Total over the vocabulary.\n */\nfunction turnIsDrawnForAPerson(initiationKind: FlowsActors_InitiationKind | null | undefined): boolean {\n if (initiationKind === null || initiationKind === undefined) return true;\n const drawn: Record<FlowsActors_InitiationKind, boolean> = {\n [FlowsActors_InitiationKind.WEBSOCKET_SESSION]: true,\n [FlowsActors_InitiationKind.A2A_REQUEST]: false,\n [FlowsActors_InitiationKind.AUTONOMOUS]: false,\n // The reply is posted in Slack or Teams as text: a card the agent showed would reach nobody (#2665).\n [FlowsActors_InitiationKind.CHAT_MESSAGE]: false,\n };\n return drawn[initiationKind];\n}\n\n/** Refused because a tool's approval gate cannot be answered as declared. */\nexport class FunctionToolApprovalGateError extends Error {}\n\n/**\n * The approval gate a tool actually has, or `undefined` for an ungated tool. The ONE reader of the two\n * declarations, so no caller re-derives which one wins.\n *\n * Throws {@link FunctionToolApprovalGateError} for a declaration nobody could answer. The registry\n * calls it at registration, so that surfaces at startup rather than on the first gated call.\n */\n// assurance-control: WILDO.AI.HUMAN_OVERSIGHT — a gated tool's call waits for the person its gate routes it to.\nexport function resolveFunctionToolApprovalGate(tool: Pick<FunctionTool, 'functionRef' | 'requiresHumanApproval' | 'humanApproval' | 'asksThePerson'>): FunctionTool_HumanApprovalGate | undefined {\n const gate = tool.humanApproval ?? (tool.requiresHumanApproval ? { route: HumanDecision_RouteKind.OWNER } : undefined);\n // #2720: a question to the person is answered by the person in the conversation, so it is gated, on the OWNER route.\n if (tool.asksThePerson && gate?.route !== HumanDecision_RouteKind.OWNER) {\n throw new FunctionToolApprovalGateError(`Function tool \"${tool.functionRef}\" asks the person and must be gated on the OWNER route: only the person whose turn it is answers it.`);\n }\n if (!gate) return undefined;\n const refuse = (why: string): never => {\n throw new FunctionToolApprovalGateError(`Function tool \"${tool.functionRef}\" declares an approval gate nobody can answer: ${why}`);\n };\n refuseUnsoundDeadlines(tool.functionRef, gate);\n // #2923: a step-up declaration that cannot mean what it says is refused here, at registration.\n const stepUpIssues = [\n ...humanDecisionStepUpDeclarationIssues(gate, 'humanApproval'),\n // #2923: and a channel declaration that names a channel that could never answer it.\n ...humanDecisionAnswerChannelsIssues(gate.answerChannels, humanDecisionStepUpRequirementOf(gate) !== undefined, 'humanApproval'),\n ];\n if (stepUpIssues.length > 0) refuse(stepUpIssues.join(' '));\n // #2967: a required qualification names a kind, once each. Whether the application DECLARES it needs the configuration,\n // which a tool does not see: the startup validator asks that.\n const requiredKinds = gate.requiredQualificationKinds ?? [];\n if (requiredKinds.some((kind) => typeof kind !== 'string' || kind.length === 0)) refuse('`requiredQualificationKinds` names an empty kind.');\n if (new Set(requiredKinds).size !== requiredKinds.length) refuse('`requiredQualificationKinds` names a kind twice.');\n switch (gate.route) {\n case HumanDecision_RouteKind.OWNER:\n if (gate.eligibleRole || gate.assignee || gate.escalateTo) {\n refuse('an OWNER route is answered by the person whose turn it is, so it takes no role, assignee or escalation target.');\n }\n if (requiredKinds.length > 0) {\n refuse('an OWNER route is answered by the person whose turn it is, who is not vetted, so it can require no qualification; route it to a ROLE.');\n }\n return gate;\n case HumanDecision_RouteKind.ROLE:\n if (!gate.eligibleRole) refuse('a ROLE route must name `eligibleRole`, the role it is routed to.');\n if (gate.assignee) refuse('a ROLE route is answered by any holder of its role; `assignee` belongs to an ASSIGNEE route.');\n return gate;\n case HumanDecision_RouteKind.ASSIGNEE:\n if (!gate.eligibleRole) refuse('an ASSIGNEE route must name `eligibleRole`, the floor its assignee must meet.');\n if (!gate.assignee) refuse('an ASSIGNEE route must declare `assignee`, the resolver of the one person it is routed to.');\n return gate;\n default: {\n const unmapped: never = gate.route;\n return refuse(`unknown route \"${String(unmapped)}\".`);\n }\n }\n}\n/**\n * Who signs a deliverable sent for electronic signature (#2293). A closed vocabulary: each member names where the person\n * comes from, so nothing the model wrote picks a signer.\n */\nexport enum FunctionTool_SignerSource {\n /** The person whose approval of the call was sealed: the approver signs what they approved. */\n APPROVER = 'approver',\n}\n\n/** A tool's electronic-signature requirement for its file deliverable (`FunctionTool.electronicSignature`, #2293). */\nexport interface FunctionTool_ElectronicSignatureRequirement {\n readonly requiredLevel: ElectronicSignature_Level;\n /** Who signs, in signing order. At least one; each source once. */\n readonly signers: readonly FunctionTool_SignerSource[];\n}\n\n/**\n * What is wrong with a tool's electronic-signature requirement (`electronicSignature`, #2293), one sentence per problem\n * with its remedy; empty when it is sound or absent. Read at registration, beside the deliverable's own declaration.\n */\nexport function functionToolElectronicSignatureDeclarationProblems(\n tool: Pick<FunctionTool, 'functionRef' | 'electronicSignature' | 'deliverableFileArgument'>,\n): string[] {\n const requirement = tool.electronicSignature;\n if (requirement === undefined) return [];\n const named = `Function tool \"${tool.functionRef}\" declares electronicSignature`;\n const problems: string[] = [];\n if (!tool.deliverableFileArgument) problems.push(`${named} and no deliverableFileArgument: only a file deliverable the approver approved by its hash can be sent for signature.`);\n if (!Object.values(ElectronicSignature_Level).includes(requirement.requiredLevel)) problems.push(`${named} with an unknown requiredLevel \"${String(requirement.requiredLevel)}\".`);\n const signers = Array.isArray(requirement.signers) ? requirement.signers : [];\n if (signers.length === 0) problems.push(`${named} with no signer: name at least one (FunctionTool_SignerSource).`);\n if (signers.some((signer) => !Object.values(FunctionTool_SignerSource).includes(signer))) problems.push(`${named} with an unknown signer source.`);\n if (new Set(signers).size !== signers.length) problems.push(`${named} naming one signer source twice.`);\n return problems;\n}\n\n/**\n * What is wrong with a tool's file-deliverable declaration (`deliverableFileArgument`, #2904), one sentence per problem\n * with its remedy; empty when it is sound or absent. Read at registration, on the schema the tool is registered with\n * (after `bindToResources`), so the argument the engine binds is the one the model is offered.\n */\nexport function functionToolDeliverableDeclarationProblems(\n tool: Pick<FunctionTool, 'functionRef' | 'deliverableFileArgument' | 'inputSchema' | 'requiresHumanApproval' | 'humanApproval' | 'asksThePerson'>,\n): string[] {\n const argument = tool.deliverableFileArgument;\n if (argument === undefined) return [];\n const problems: string[] = [];\n const named = `Function tool \"${tool.functionRef}\" declares deliverableFileArgument \"${String(argument)}\"`;\n if (typeof argument !== 'string' || argument.trim().length === 0) return [`${named}, which names no argument: name the argument holding the file's id.`];\n if (!tool.humanApproval && !tool.requiresHumanApproval) {\n problems.push(`${named} and is not approval-gated: a file deliverable is bound by the approval of the call, so gate it (humanApproval or requiresHumanApproval).`);\n }\n if (tool.asksThePerson) problems.push(`${named} and asks the person: a question approves no file.`);\n const shape = tool.inputSchema instanceof z.ZodObject ? (tool.inputSchema.shape as Record<string, z.ZodTypeAny>) : undefined;\n const declared = shape?.[argument];\n if (!declared) {\n problems.push(`${named}, which is not a top-level argument of its input schema: declare it there as the file's id (a string).`);\n } else if (!isStringArgumentSchema(declared)) {\n problems.push(`${named}, which is not a string argument: a file deliverable is named by its file id.`);\n }\n return problems;\n}\n\n/**\n * What is wrong with a tool's record-approval declarations (`sealedRecordFields`, `approvalReplacesEarlierApprovalOfRow`,\n * #2914), one sentence per problem with its remedy; empty when they are sound or absent. `declaredFieldsOf` answers the\n * fields the resource's main schema declares, or undefined when the resource is not registered (its fields are then not\n * checked here: a field the row does not hold is shown and sealed as absent).\n */\nexport function functionToolRecordApprovalDeclarationProblems(\n tool: Pick<FunctionTool, 'functionRef' | 'sealedRecordFields' | 'approvalReplacesEarlierApprovalOfRow' | 'argumentsResource' | 'requiresHumanApproval' | 'humanApproval' | 'asksThePerson'>,\n declaredFieldsOf?: (resourceType: string) => readonly string[] | undefined,\n): string[] {\n const fields = tool.sealedRecordFields;\n const replaces = tool.approvalReplacesEarlierApprovalOfRow === true;\n if (fields === undefined && !replaces) return [];\n const problems: string[] = [];\n const named = `Function tool \"${tool.functionRef}\" declares ${fields !== undefined ? 'sealedRecordFields' : 'approvalReplacesEarlierApprovalOfRow'}`;\n if (!tool.humanApproval && !tool.requiresHumanApproval) {\n problems.push(`${named} and is not approval-gated: it describes what an approval covers, so gate it (humanApproval or requiresHumanApproval).`);\n }\n if (tool.asksThePerson) problems.push(`${named} and asks the person: a question approves no record.`);\n if (!tool.argumentsResource?.rowIdArgument) {\n problems.push(`${named} without argumentsResource.rowIdArgument: name the argument holding the id of the row the approval is about.`);\n }\n if (fields !== undefined) {\n if (!Array.isArray(fields) || fields.length === 0 || fields.some((field) => typeof field !== 'string' || field.trim().length === 0)) {\n problems.push(`${named}, which names no field: list the fields of the row the approval covers.`);\n } else {\n const duplicated = fields.filter((field, index) => fields.indexOf(field) !== index);\n if (duplicated.length > 0) problems.push(`${named}, which names ${[...new Set(duplicated)].join(', ')} more than once.`);\n const declared = tool.argumentsResource ? declaredFieldsOf?.(tool.argumentsResource.resourceType) : undefined;\n const unknown = declared ? fields.filter((field) => !declared.includes(field)) : [];\n if (unknown.length > 0) problems.push(`${named}, naming ${unknown.join(', ')}, which ${tool.argumentsResource!.resourceType} does not declare.`);\n }\n }\n return problems;\n}\n\n/** Whether an argument schema is a string once its optional, nullable and default wrappers are removed. */\nfunction isStringArgumentSchema(schema: z.ZodTypeAny): boolean {\n let current: z.ZodTypeAny = schema;\n for (let depth = 0; depth < 8; depth += 1) {\n if (current instanceof z.ZodOptional || current instanceof z.ZodNullable || current instanceof z.ZodDefault) {\n current = current.def.innerType as z.ZodTypeAny;\n continue;\n }\n return current instanceof z.ZodString || (current as { def?: { type?: unknown } }).def?.type === 'string';\n }\n return false;\n}\n\n/** @wildo_source:part:end saas.backend.flows-actors.function-tool */\n\n/**\n * Refuse a deadline declaration that could never do what it says (#1628), at registration. The calendar\n * half (a CALENDAR clock with no `reviewCalendar`) needs the application configuration, which a tool does\n * not see, so the startup validator asks that one; everything else is decided here.\n */\nfunction refuseUnsoundDeadlines(functionRef: string, gate: FunctionTool_HumanApprovalGate): void {\n const deadlines = gate.deadlines;\n if (!deadlines) return;\n const issues = reviewDeadlinesDeclarationIssues(\n { ...deadlines, rules: deadlines.rules?.map(({ stage, action }) => ({ stage, action })) },\n { routeKind: gate.route, calendarDeclared: true },\n );\n for (const rule of deadlines.rules ?? []) {\n if (rule.action === ReviewEscalationActionKind.REASSIGN && !rule.target) {\n issues.push(`deadlines.rules REASSIGNs at ${rule.stage} but names no \\`target\\`; a reassignment is never inferred.`);\n }\n if (rule.action === ReviewEscalationActionKind.NOTIFY && rule.target) {\n issues.push(`deadlines.rules NOTIFIES at ${rule.stage} but names a \\`target\\`, which only a REASSIGN rule uses.`);\n }\n }\n if (issues.length > 0) {\n throw new FunctionToolApprovalGateError(`Function tool \"${functionRef}\" declares deadlines that cannot work:\\n - ${issues.join('\\n - ')}`);\n }\n}\n\n/**\n * The name a `functionRef` is exposed to the model under.\n *\n * A `functionRef` uses dots, and a model API accepts only the portable set\n * (`toPortableModelToolName`), so the two differ for every tool. An overlong ref is also shortened. ONE definition, because the mapping is used in opposite directions by two sites: the\n * turn BUILDS the tool set from refs, and a resume that re-signs a modified approval must find the\n * FunctionTool behind a name it reads back out of the model SDK's own message array. A second copy\n * of this expression would make an approval unmodifiable for exactly the refs the two spelled\n * differently.\n *\n * Not injective by construction (`a.b` and `a_b` collapse), and deliberately not made so: the\n * forward direction is what the model sees, and a reverse lookup resolves against ONE agent's\n * declared refs, where a collision is an authoring defect. The turn keeps the first ref and reports\n * the second, which is also the ref a reverse lookup finds first.\n */\nexport function modelToolNameForFunctionRef(functionRef: string): string {\n return toPortableModelToolName(functionRef);\n}\n\n/**\n * The label key one slot of a registered function tool is worded under (#2551): `flows_actors_tools.<model tool\n * name>.<slot>`, derived from the tool's `functionRef` through {@link modelToolNameForFunctionRef}.\n *\n * The labelling planner plans it from every `functionRef` an application registers, and the conversation reads it from\n * the trace's `toolName`, which IS that model tool name. Going through this one function is what keeps the two equal.\n */\nexport function functionToolLabelKey(functionRef: string, slot: FlowsActorsToolLabelSlot): string {\n return flowsActorsToolLabelKey(modelToolNameForFunctionRef(functionRef), slot);\n}\n\n/**\n * The agent an actor system converses through: its first AGENTIC actor bound to an agent. ONE definition, because a\n * conversation picks its agent by it and whatever reads a settled tool call back (an approval's edit, an exported\n * correction, #1923) must resolve the same agent's tools.\n */\nexport function chatAgentRefOfActorSystem(actorSystem: Pick<ActorSystem, 'actors'>): string | undefined {\n // The shared rule (`conversationalActorOf`), so the browser names the same actor the runtime runs (#2524).\n return conversationalActorOf(actorSystem.actors)?.agentRef;\n}\n\n/** Uniform, model-facing result shape for read tools. */\ninterface ResourceReadToolResult {\n data: unknown[];\n pagination?: unknown;\n truncated?: boolean;\n /**\n * The call carried a `searchQuery` and no search ran — the SEARCH it reached failed, or the resource exposes none — so\n * the answer is the filtered LIST, and these rows are NOT matches for the text (#2769). Said to the model in `note`, and\n * stored on the trace, so neither the reply nor the card presents every record as what the text found. A resource whose\n * SEARCH cannot take text is not offered `searchQuery` at all (`bindToResources`), so this marks a run-time failure.\n */\n searchQueryNotApplied?: true;\n /** What the model must know about this answer, in its own words; set only with {@link searchQueryNotApplied}. */\n note?: string;\n}\n\n/** What the model is told when its search text could not be applied (#2769). Model-facing, never shown to a person. */\nconst SEARCH_QUERY_NOT_APPLIED_NOTE = 'The searchQuery was NOT applied: the text search could not run this time. '\n + 'These are the records the filters allow, not records matching the text. Do not present them as matches; narrow with '\n + 'filters, or say the text search failed.';\n\n/**\n * Normalize a handler list/search result (array or paginated) to the tool result shape.\n *\n * `truncated` says MORE records matched than came back. A paginated answer is already cut to the page by the\n * repository, so its rows never exceed `limit`: what says more exist is the envelope's `total`. Reading only the row\n * count told the model (and the person, through the card) that 50 of 60 pending todos were all of them.\n */\nfunction toReadResult(result: unknown, limit: number): ResourceReadToolResult {\n if (Array.isArray(result)) {\n return { data: result.slice(0, limit), truncated: result.length > limit };\n }\n if (result && typeof result === 'object' && 'data' in result && Array.isArray((result as { data: unknown[] }).data)) {\n const paged = result as { data: unknown[]; pagination?: { total?: unknown } };\n const data = paged.data.slice(0, limit);\n const total = paged.pagination?.total;\n const truncated = paged.data.length > limit || (typeof total === 'number' && total > data.length);\n return { data, pagination: paged.pagination, truncated };\n }\n return { data: [] };\n}\n\n/**\n * Resolve the operation a tool DISPATCHES for `(resourceType, operationIdentifier)`: the\n * URL-BEARING default, and nothing else.\n *\n * ## The defect this closes — `authorize ≡ advertise ≡ execute`\n *\n * Both factories used to resolve through `getServiceOperationPathDefault`, and they dispatched\n * through the `ServicesRegistryHandlerBackendService` convenience verbs (`create` / `update` /\n * `list` / `search`), which re-resolve the same way. That resolver PREFERS an `INTERNAL_CALL`\n * default over the URL-bearing one — deliberately, because it is the SERVICE layer's native\n * transport and the trusted internal callers it was written for want exactly that. This plane is\n * not one of them: it faces an external principal and advertises a public operation to a model.\n *\n * So for a resource declaring BOTH defaults, the tool advertised one operation and executed\n * another — a different `requestDto` validating the model's arguments, a different response DTO,\n * a different `roles` declaration, and different prefix / postfix / custom-impl side effects.\n *\n * **Measured 2026-09-08, and exactly one resource declares both: `organizations` CREATE.** The\n * divergence there is not cosmetic. Its `INTERNAL_CALL` default is the transport registration owns,\n * so the shared CREATE prefix treats that path as registration-managed and SKIPS the\n * `org_type_creation_restricted` guard that confines creation-policy-managed organization types to\n * the registration flow; and the founding-owner postfix is registered on the DEFAULT `API_CALL`\n * variant ONLY, so the internal path writes no owner membership. An agent tool wired to\n * `resourceWriteTool(ORGANIZATIONS, CREATE)` therefore created a tenant with no owner — precisely\n * the stranded state `administrative-continuity-floors.md` exists to prevent — while also reaching\n * a restricted organization type. The MCP tool plane had already made this exact decision and wrote\n * down the reasoning (`McpServerBackendService.callTool`); this plane simply had not.\n *\n * ## Why \"no URL-bearing default\" now REFUSES, and why that is the safe direction\n *\n * This is a behaviour change, and it is intended. A resource whose only default for an identifier\n * is `INTERNAL_CALL` has NO HTTP surface, and its author reasoned from exactly that: `users` LIST\n * declares `roles: []` and says in as many words that the empty set \"is inert here precisely\n * because it is not URL-bearing\". A tool that dispatched it made a route-less, deliberately\n * unexposed operation reachable by an external agent — the opposite of what the declaration\n * assumed. Refusing is fail-closed, and the refusal names the resource and the operation so an app\n * author who genuinely wants that surface exposed can declare a URL-bearing default for it.\n *\n * @returns the URL-bearing default operation, or `undefined` when the resource declares none.\n */\nfunction resolveDispatchableOperation(\n principal: ResourceOperationDispatchPrincipal,\n resourceType: ResourceType,\n operationIdentifier: string,\n): ResourceConfiguration_Operation<any, any, any> | undefined {\n const { resourcesRegistry } = principal.services;\n // Non-throwing probe FIRST: `getOperationPathDefault` mints an alert-grade INTERNAL error on its\n // miss path, and merely CONSTRUCTING a Wildo error fires its backend actions (LOG / ALERT /\n // METRICS) before any `catch` could downgrade them. A resource with no URL-bearing default for\n // this identifier is an ordinary, expected shape here — not an incident.\n if (!resourcesRegistry.hasOperationPathDefault(resourceType, operationIdentifier)) {\n return undefined;\n }\n return resourcesRegistry.getOperationFromPath(\n resourcesRegistry.getOperationPathDefault(resourceType, operationIdentifier),\n );\n}\n\n/**\n * What a tool may learn about the application's resources when it is registered ({@link FunctionTool.bindToResources}):\n * the operation a tool would DISPATCH for `(resourceType, operationIdentifier)` — the URL-bearing default, by the same\n * rule a tool's dispatch resolves it — or `undefined` when the resource exposes none. One rule for what a tool offers\n * and what it runs, so the two cannot disagree.\n */\nexport interface FunctionToolResourceDeclarations {\n dispatchableOperationOf(resourceType: ResourceType, operationIdentifier: string): ResourceConfiguration_Operation<any, any, any> | undefined;\n /**\n * The field the resource's primary scope fills from the request's own context (`organizationId` for an organization\n * resource), or `undefined`. A read tool does not offer it as a filter: the conversation's scope decides it, and the\n * repository refuses a caller value that disagrees (`applyAuthoritativeContextFilterValue`), so offering it would only\n * give the model a way to be refused.\n */\n primaryScopeFieldOf(resourceType: ResourceType): string | undefined;\n}\n\n/** A calendar day or an instant, as a model writes one in a date-range filter. */\nconst ReadToolFilterInstantSchema = z.union([z.iso.date(), z.iso.datetime({ offset: true })]);\n\n/** A range that bounds nothing filters nothing, and an empty object reaches the repository as a value it cannot cast. */\nconst hasABound = (range: Record<string, unknown>): boolean => Object.values(range).some((bound) => bound !== undefined);\n\n/** A declaration's own type under `.optional()` / `.nullable()` / `.default()`, which say nothing about what it filters by. */\nfunction unwrapFilterDeclaration(declaration: unknown): unknown {\n let current = declaration;\n while (current instanceof z.ZodOptional || current instanceof z.ZodNullable || current instanceof z.ZodDefault) current = current.unwrap();\n return current;\n}\n\n/**\n * What a model may send for ONE declared filter field, or `undefined` for a declaration it cannot express — a\n * cross-resource filter reference (a function), or a shape this plane does not read. The same classes the search request\n * schema distinguishes (`createResourceSearchQueryRequestSchema`): an equality on an enum, a string, a number or a\n * boolean, and a range on a date, a number or a year-month. A date range is written as ISO strings here, since a model writes text, and\n * read back as instants by {@link readToolFilterOf}.\n */\nfunction readToolFilterFieldSchema(declared: unknown): z.ZodTypeAny | undefined {\n if (typeof declared === 'function') return undefined;\n if (isResourcesFilterNumberRangeSchema(declared)) return Resources_Filter_NumberRangeSchema.refine(hasABound, 'Give min, max, or both.');\n // A range of months (#3435), offered as the range alone: one month is the range that starts and ends with it, so the\n // model has one shape to write. Strict (the vocabulary is a strict object), so a bound under another vocabulary's name is refused here rather than\n // reaching the repository as a key no store compiles. Each bound keeps the vocabulary's `YYYY-MM` pattern.\n if (isResourcesFilterYearMonthRangeSchema(declared)) return Resources_Filter_YearMonthRangeSchema.refine(hasABound, 'Give startMonth, endMonth, or both.');\n const declaration = unwrapFilterDeclaration(declared);\n if (declaration instanceof z.ZodDate) {\n return z.strictObject({\n startDate: ReadToolFilterInstantSchema.optional().describe('The earliest date or instant to include (ISO 8601). A calendar day starts at 00:00 UTC. Omit for no lower bound.'),\n endDate: ReadToolFilterInstantSchema.optional().describe('The latest date or instant to include (ISO 8601). A calendar day includes the WHOLE day, to 23:59:59.999 UTC. Omit for no upper bound.'),\n }).refine(hasABound, 'Give startDate, endDate, or both.');\n }\n if (declaration instanceof z.ZodEnum) return z.enum(declaration.options as [string, ...string[]]);\n // A Zod 4 string FORMAT (`z.uuid()`, `z.email()`) is not `instanceof z.ZodString`; every one extends the core\n // `$ZodString`, which is what the search request schema's own builder asks too. The declared length bounds are\n // carried (#2815): the controller refuses a value past them (`assertCollectionFilterValuesMatchPublishedSchemas`), and\n // this tool dispatches around the controller, so its own parse is the only place they can be held. Formats are not:\n // a model filters by the value it read, whatever its shape.\n if (declaration instanceof z.core.$ZodString) {\n const declaredBounds = declaration as { readonly minLength?: number | null; readonly maxLength?: number | null };\n const atLeastOne = z.string().min(Math.max(1, declaredBounds.minLength ?? 1));\n return typeof declaredBounds.maxLength === 'number' ? atLeastOne.max(declaredBounds.maxLength) : atLeastOne;\n }\n if (declaration instanceof z.ZodNumber) return z.number();\n if (declaration instanceof z.ZodBoolean) return z.boolean();\n return undefined;\n}\n\n/** The fields a read tool may filter by, keyed as the operation declares them, with what each accepts. */\nfunction readToolFilterFieldsOf(operation: ResourceConfiguration_Operation<any, any, any> | undefined, primaryScopeField?: string): Record<string, z.ZodTypeAny> {\n const declared = (operation as { filterFields?: Record<string, unknown> } | undefined)?.filterFields ?? {};\n const fields: Record<string, z.ZodTypeAny> = {};\n for (const [key, declaration] of Object.entries(declared)) {\n if (key === primaryScopeField) continue;\n const schema = readToolFilterFieldSchema(declaration);\n if (schema) fields[key] = schema.optional();\n }\n return fields;\n}\n\n/** The keys of a range filter's object (a refined object keeps them on its `shape`), or `undefined` for any other filter. */\nfunction readToolRangeShapeOf(schema: unknown): Record<string, unknown> | undefined {\n return schema instanceof z.ZodObject ? (schema.shape as Record<string, unknown>) : undefined;\n}\n\n/** A field's filter as a model reads it in the tool's description: its name, and its values when it has a closed set. */\nfunction describeReadToolFilterField(key: string, schema: z.ZodTypeAny): string {\n const inner = schema instanceof z.ZodOptional ? schema.unwrap() : schema;\n if (inner instanceof z.ZodEnum) return `${key} (one of: ${(inner.options as string[]).join(', ')})`;\n const range = readToolRangeShapeOf(inner);\n if (range && 'startDate' in range) return `${key} (a date range: startDate / endDate)`;\n if (range && 'startMonth' in range) return `${key} (a range of months: startMonth / endMonth, each YYYY-MM, both included)`;\n if (range) return `${key} (a number range: min / max)`;\n return key;\n}\n\n/** An ISO calendar day (`2026-10-12`), as opposed to an instant. */\nconst ISO_CALENDAR_DAY = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst LAST_MILLISECOND_OF_A_DAY = 24 * 60 * 60 * 1000 - 1;\n\n/**\n * A date bound as the instant the repository compares with (`$gte` / `$lte`). A calendar-day END bound is the day's\n * last millisecond: a person asking for \"due by the 12th\" means the 12th included, and the day's midnight would leave out\n * everything due on it after 00:00. Calendar days are UTC days; the tool knows no time zone, and says so to the model.\n */\nfunction readToolDateBoundOf(bound: string, side: 'start' | 'end'): Date {\n const instant = new Date(bound);\n return side === 'end' && ISO_CALENDAR_DAY.test(bound) ? new Date(instant.getTime() + LAST_MILLISECOND_OF_A_DAY) : instant;\n}\n\n/**\n * Whether a read tool's SEARCH can take a text: it is `isSearchable` and names `searchableFields` — the predicate both\n * repositories refuse a term by (`repository-resource` and the PostgreSQL repository's search preflight, #2510).\n */\nfunction readToolSearchesText(search: ResourceConfiguration_Operation<any, any, any> | undefined): boolean {\n const declared = search as { isSearchable?: boolean; searchableFields?: readonly unknown[] } | undefined;\n return declared?.isSearchable === true && (declared.searchableFields?.length ?? 0) > 0;\n}\n\n/**\n * The repository filter for a read tool's `filters` argument: a date range's ISO strings as instants, every other value\n * as sent. `undefined` when nothing is filtered. The schema already admitted only declared keys and their shapes, and a\n * range with no bound; one is still dropped here, since an empty object reaches the repository as a value it cannot cast.\n */\nfunction readToolFilterOf(filters: Record<string, unknown> | undefined): Record<string, unknown> | undefined {\n if (!filters) return undefined;\n const filter: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(filters)) {\n if (value === undefined) continue;\n if (value && typeof value === 'object') {\n const range = value as Record<string, unknown>;\n if (!hasABound(range)) continue;\n if ('startDate' in range || 'endDate' in range) {\n filter[key] = {\n ...(typeof range.startDate === 'string' ? { startDate: readToolDateBoundOf(range.startDate, 'start') } : {}),\n ...(typeof range.endDate === 'string' ? { endDate: readToolDateBoundOf(range.endDate, 'end') } : {}),\n };\n continue;\n }\n }\n filter[key] = value;\n }\n return Object.keys(filter).length > 0 ? filter : undefined;\n}\n\n/** {@link resolveDispatchableOperation}, refusing rather than returning `undefined`. */\nfunction requireDispatchableOperation(\n principal: ResourceOperationDispatchPrincipal,\n plane: ResourceOperationSeamPlane,\n resourceType: ResourceType,\n operationIdentifier: string,\n): ResourceConfiguration_Operation<any, any, any> {\n const operation = resolveDispatchableOperation(principal, resourceType, operationIdentifier);\n if (!operation) {\n throw new Error(\n `${OPERATION_DISPATCH_PLANE_FACTS[plane].callerLabel} for \"${resourceType}.${operationIdentifier}\": the resource declares no default `\n + 'URL-bearing variant for this operation, so there is no publicly-advertised operation to dispatch. Declare an '\n + 'API_CALL default for it, or expose a different operation.',\n );\n }\n return operation;\n}\n\n/**\n * Apply the dispatched operation's OWN `roles` ACL — the gate this plane was missing entirely.\n *\n * ## What was broken\n *\n * A function tool dispatches a resource operation through\n * `ServicesRegistryHandlerBackendService`, i.e. it enters at the SERVICE tier. The service tier\n * applies the repository's contextual filter (tenancy, FK narrowing, unit narrowing, the anonymous\n * guard, the retention row-hide — all fail-closed) and the whole operation pipeline (Zod, enabled\n * conditions, custom impl, hooks). It applies NO role check, and that is deliberate and\n * load-bearing: its dominant population is authentication, SCIM provisioning, webhook routing and\n * sweeps, which run BEFORE a role-bearing principal exists. Enforcing declared roles there would\n * deny the reads that ESTABLISH identity.\n *\n * `AuthorizationsBackendService.authorizeInController` is therefore the ONLY place an operation's\n * declared `roles` are checked, and it is mounted at the CONTROLLER tier — the boundary, because\n * that is where an untrusted principal names an operation.\n *\n * **This plane is that boundary and did not ask.** A tool call arrives from an external principal\n * (an A2A agent's token, or a user's own WebSocket) naming an operation on their own authority, and\n * dispatched it with the role ACL unread. A caller whose roles the operation refuses, but whose\n * tenancy admits the row, succeeded — so `roles: [ORG_MEMBER]` on Wonder Todos' todos CREATE, and\n * `roles: [APP_USER]` on the organizations self-service CREATE, were both statements about the HTTP\n * door only. Worse, the factories' own JSDoc, the app's registration comment and\n * `authenticateExternalToken`'s contract all asserted the opposite, so the gap read as closed.\n *\n * The MCP plane, which faces the same class of caller through a different transport, has always run\n * this gate (`McpServerBackendService.callTool`). This is the same call, on the sibling plane.\n *\n * ## Collection vs row\n *\n * `idOrIds` is `undefined` for CREATE / LIST / SEARCH (collection: roles + parent scope) and the\n * addressed record id for UPDATE (row: additionally FK reachability and per-row access). Passing a\n * value in the row's place for a collection call would authorize a READ of a row whose id happens\n * to be a scope id — a question nobody asked, failing for the wrong reason.\n *\n * Refusals are recorded by the authorizer's own denial-audit funnel, so a tool call denied here\n * produces the same `RESOURCE_OPERATION_DENIED` evidence a denied HTTP request produces.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — an external caller reaching a resource operation\n * off the HTTP plane is held to that operation's own declared authority, through the same predicate.\n *\n * @throws AUTHORIZATION — surfaced to the model as a tool error, so the agent can say it was refused.\n */\nasync function authorizeToolDispatch(\n principal: ResourceOperationDispatchPrincipal,\n executionContext: ExecutionContext<any>,\n idOrIds?: string,\n): Promise<void> {\n await principal.services.authorizer.authorizeInController(idOrIds, executionContext);\n}\n\n/**\n * Charge ONE dispatch against the operation's own authored `rateLimit?` policy, before the\n * dispatch happens.\n *\n * ## What was broken\n *\n * `rateLimit?` is authored on an `API_CALL` variant and had exactly\n * two consumers: `RateLimitBackendService.checkPolicyForVariant` at the HTTP controller\n * pre-flight, and `McpServerBackendService.assertOperationRateLimitPolicy` on the MCP tool plane.\n * The factories below dispatch the SAME operations through the SAME service pipeline while\n * bypassing Express entirely, so the identical operation was throttled over REST, throttled over\n * MCP, and unthrottled as an agent tool.\n *\n * The exposure is larger here than on either of those planes, which is why this is not merely a\n * consistency fix. A2A's blanket per-principal cap (`A2A_EXTERNAL_TURN_RATE_MAX`) bounds TURNS,\n * and one turn's tool loop may issue arbitrarily many tool calls — so an operation declaring\n * `requestsPerMinute: 5` could be dispatched far more than five times a minute by an external\n * caller spending a single turn. MCP has no such multiplier: one `tools/call` is one dispatch, so\n * its transport cap bounds dispatches 1:1.\n *\n * ## The policy is read off the operation actually being DISPATCHED — which is now the right one\n *\n * This guard originally re-resolved the URL-bearing default for itself, because the factories\n * dispatched the `INTERNAL_CALL` default and `rateLimit?` does not exist on that variant at all —\n * so reading the dispatched operation would have made the guard permanently inert for precisely\n * the resources that declare both. That divergence is gone: {@link resolveDispatchableOperation}\n * makes the URL-bearing default the dispatched operation, and this function takes it as an\n * argument. Policy-source and dispatch-target are now the same object rather than two resolutions\n * that agreed by discipline — which is what stops them separating again.\n *\n * Reading a single declaration as the OPERATION's budget is the framework's own established\n * reading of the field, not an invention: `resources-config.shared.factory.ts` projects\n * `rateLimit: defaultApiCallVariant.rateLimit` onto every derived auto-variant, stating that \"a\n * single declaration on the default URL-bearing variant covers all derived auto-variants\".\n *\n * ## Subject: the CREDENTIAL, not the tenant\n *\n * See {@link resolveDeclaredPolicySubjectKey} for the full argument. In short, an authored\n * `requestsPerMinute` has always meant \"per CLIENT\" — the HTTP seam keys on the source IP — so\n * the faithful translation onto a plane whose callers are credentials is the credential, then the\n * delegated user, then the owning scope. Keying on the tenant would silently make the same\n * declared number several times stricter here than over REST for any tenant running more than one\n * agent. Every branch reads a SERVER-VERIFIED field of the caller's auth; nothing here may ever be\n * sourced from a tool argument, or the throttle becomes opt-out by a model choosing a fresh bucket.\n *\n * ## Scope: a THIRD bucket, deliberately\n *\n * `agent-tool:resource:<resource>:<operation>`, distinct from the HTTP seam's\n * `resource:<resource>:<operation>` and MCP's `mcp:resource:<resource>:<operation>`. The three\n * count different SUBJECTS (an IP, a credential, a credential on a different transport); one\n * shared bucket would mix identity spaces and let a browser's traffic spend an agent's budget.\n * A chat command counts in a fourth, `chat-command:resource:<resource>:<operation>` (#2666 S7): its\n * subject is the linked member, whose commands must not spend the budget of their own agent's tools.\n *\n * ## Ordering: AFTER authorization\n *\n * Reversed 2026-09-08, when the role gate landed beside it, and MCP's argument is adopted verbatim:\n * a caller who may not run the operation at all must be refused with AUTHORIZATION rather than told\n * how much of a budget they have, and must not consume a slot of a budget that is not theirs —\n * which would let an unauthorized caller exhaust an authorized one's quota. The HTTP route takes the\n * same order for a signed-in caller (#2949), and counts before authorization only a caller with no\n * verified identity, per source address.\n *\n * ## Postures\n *\n * - **No declared policy, or a non-HTTP default** -> no-op, zero Redis traffic. The overwhelmingly\n * common case: most operations declare nothing.\n * - **Unkeyable subject with a policy declared** -> REFUSE. This diverges from MCP's\n * proceed-and-log, and the reason is the tool-loop multiplier described above: there, an\n * unkeyed call is still bounded 1:1 by the transport's per-principal cap, so proceeding costs a\n * bounded amount; here an unkeyed turn could drive an uncounted, unbounded loop against an\n * endpoint whose author asked for a budget. The branch is structurally unreachable — a tool runs\n * only inside an authenticated turn, and an authenticated principal always carries one of the\n * four identity fields — so the refusal costs nothing today and cannot decay into a silent hole.\n * - **Limiter outage** -> propagates, exactly as it does over HTTP and MCP for the same declared\n * policy. An authored budget must not quietly become \"unlimited\" on one plane while it is a 500\n * on the others. (Contrast `assertExternalTurnWithinRate`, the framework-default abuse throttle,\n * which counts in process on an outage, #3275, because nobody declared it.)\n *\n * ## A refusal is recorded, once per subject per window (#3008)\n *\n * Each declared window's FIRST refusal (the limiter reports it through `onFirstRefusalOfWindow`) leaves one\n * `OPERATION_RATE_LIMIT_REFUSED` row naming this plane, the operation, the subject counted and the window, written by\n * `recordOperationRateLimitRefusal`, the helper the MCP plane uses too, against the execution context built for this\n * operation. Fire-and-forget through the optional `services.auditLogs`: the refusal is thrown without waiting, and a\n * plane assembled without the audit service still refuses, unrecorded.\n *\n * ## Call-site enumeration, so the next reader does not re-derive it\n *\n * The invariant is \"a resource operation dispatched on behalf of an external CLIENT is charged\n * against its declared budget\". Enumerated 2026-09-08 over every caller of the generic service\n * dispatch (`doByOperationPath` and the `ServicesRegistryHandlerBackendService` verbs):\n *\n * | Plane | Verdict |\n * |---|---|\n * | REST route (`ControllerResourceBackendService.doOperation`) | charged once — a signed-in person or a machine by `assertDeclaredRateLimitForHttpCaller` once authorized, per credential or person (`OperationDispatchPlane.HTTP_ROUTE`, #2949); anyone else by `assertDeclaredRateLimitForHttpAddress` → `checkPolicyForVariant`, IP-keyed |\n * | MCP `tools/call` (`McpServerBackendService`) | charged — `checkPolicyForSubject`, credential-keyed, its own path (`OperationDispatchPlane.MCP_TOOL`) |\n * | Agent function tool (here; reachable over A2A and the app WebSocket) | charged — this function |\n * | Chat command (`OperationDispatchPlane.CHAT_COMMAND`, #2666 S7) | charged — this function, through the same seam, in its own bucket |\n * | Queue job executor (`job-executor.backend.service.ts`) | **N/A** — a REPLAY of an operation already authorized, and already charged, at enqueue time (`isWorkerExecution: true`). Charging again would double-count one client request and throttle a background worker against a client's budget |\n * | Minion-scoped handler (`saas-minions-lib`) | **N/A** — same worker plane, one scope deeper |\n * | Custom controllers (SCIM, charts, flows-actors) | **N/A** — the separate authoring surface: they declare their own policy and call `checkPolicy` inline (SCIM does, with its own scope key) rather than inheriting a resource operation's |\n * | Engine-internal collaborators (auth, org, RAG, seeding, retention) | **N/A** — not client-driven; reached from a plane that already charged, or from a system path with no client at all |\n * | Agent retrieval tool (`retrievalTool`, #2300) | **N/A** — client-driven, but it dispatches no resource operation: it searches the index and re-reads each matched row at the service tier, as the HTTP feature that offers retrieval (an application's own `ask`-style operation) charges only its own operation and never those reads. Bounded by the turn's step limit and the A2A turn budget, not by a resource operation's |\n *\n * The rule that generalises: a NEW plane that dispatches a resource operation on a client's behalf\n * owes its own `checkPolicyForSubject` call — AND its own `authorizeInController`. Nothing\n * structural forces either; both fields are simply unread where nobody reads them, which is how\n * both the MCP plane and this one shipped unthrottled, and how this one shipped unauthorized.\n *\n * @throws RATE_LIMIT (429) carrying `context.retryAfterSeconds` — the same envelope the HTTP and\n * MCP seams throw, so one refusal vocabulary covers all three planes. The AI SDK surfaces it to\n * the model as a tool error, so the agent can tell the user it is being throttled.\n */\n// assurance-control: WILDO.OPERATIONS.AUTHENTICATED_BURST_LIMIT — an agent tool's or chat command's call past its operation's declared window is refused before dispatch, counted per client, and its window's first refusal recorded.\nasync function assertDeclaredOperationRateLimit(\n principal: ResourceOperationDispatchPrincipal,\n plane: ResourceOperationSeamPlane,\n operation: ResourceConfiguration_Operation<any, any, any>,\n resourceType: ResourceType,\n operationIdentifier: string,\n executionContext: ExecutionContext<any>,\n): Promise<void> {\n // Defensive: `resolveDispatchableOperation` already filters to URL-bearing variants, so this\n // narrow exists to reach `rateLimit` on the union rather than to exclude a reachable case.\n if (\n operation.variantType !== ResourceOperationVariantType.API_CALL\n ) {\n return;\n }\n const policy = operation.rateLimit;\n if (!policy) {\n return;\n }\n\n const subject = resolveDeclaredPolicySubject(principal.auth?.initiatorIds);\n const { callerLabel } = OPERATION_DISPATCH_PLANE_FACTS[plane];\n if (!subject) {\n throw new Error(\n `${callerLabel} for \"${resourceType}.${operationIdentifier}\": the operation declares a rateLimit policy but the `\n + 'caller carries no server-verified identity to count it against, so the declared budget cannot be honoured.',\n );\n }\n\n // #3008: each window's first refusal is recorded, naming this plane, through the one helper the MCP plane uses too.\n await principal.services.rateLimitService.checkPolicyForSubject(\n policy,\n declaredRateLimitScopeKey(plane, resourceType, operationIdentifier),\n declaredPolicySubjectKey(subject),\n principal.organizationId,\n {\n onFirstRefusalOfWindow: (refusal) => recordOperationRateLimitRefusal(\n { auditLogs: principal.services.auditLogs },\n { plane, resourceIdentifier: resourceType, operationIdentifier, subject, refusal, executionContext },\n ),\n },\n );\n}\n\n/**\n * Dispatch a resource operation from a function tool, carrying BOTH gates the service tier skips.\n *\n * ## What this exists to prevent (#556)\n *\n * A `FunctionTool` enters at the SERVICE tier. It never passes through Express, so two\n * controller-tier gates are simply absent from its path — the operation's declared `roles` ACL and\n * its declared `rateLimit?`. That skip is CORRECT for the service tier's intended caller (the\n * authentication reads that run before a role-bearing principal exists) and wrong for this plane,\n * whose caller is an external principal naming an operation on their own authority.\n *\n * The failure is quiet, which is what makes it worth a seam. Tenancy still applies — the\n * repository's contextual filter runs regardless — so an unauthorized tool returns the caller's own\n * tenant's rows and LOOKS like it works. Nothing throws and nothing logs. What is missing is only\n * the row-level `roles` ACL: a caller whose roles the operation refuses, but whose tenancy admits\n * the row, succeeds.\n *\n * Until this existed the two gates were applied by hand at three sites in this file, and both helpers\n * were module-private — so an application author writing their own tool could not discharge the\n * obligation even after reading about it. The engine's own rule\n * (`invariant-call-site-enumeration.md`) asks for the opposite: prefer making the invariant\n * unbypassable over applying it N times. **This is the shortest path to a dispatch, so the correct\n * path is also the easy one.**\n *\n * ## The order is authorize → charge → dispatch, and it is not arbitrary\n *\n * Authorization first, so an unauthorized caller cannot spend an authorized caller's quota. The\n * charge before the dispatch, so a refused budget costs no work. This is the same order the MCP\n * plane uses, deliberately — one refusal vocabulary across every plane that enters here.\n *\n * ## One id, two uses, and why that is safer than two parameters\n *\n * `recordId` addresses the row AND is the authorization subject, because at every existing call site\n * those are the same value: an UPDATE passes the id to both, a CREATE/LIST/SEARCH passes it to\n * neither. Splitting them into two parameters would make it possible to authorize a collection call\n * while dispatching a row call — a question nobody asked, failing for the wrong reason. A bulk\n * operation addressed by a FILTER passes `dispatchFilter` instead, which is never an authorization\n * subject because a filter-addressed operation IS a collection call.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — an external caller reaching a resource operation\n * off the HTTP plane is held to that operation's own declared authority, through the same predicate.\n *\n * @throws AUTHORIZATION when the operation's roles refuse the caller — surfaced to the model as a\n * tool error, so the agent can say it was refused. Recorded by the authorizer's own denial-audit\n * funnel, so the evidence matches a denied HTTP request.\n * @throws RATE_LIMIT (429) carrying `context.retryAfterSeconds`, the same envelope the HTTP and MCP\n * seams throw.\n * @throws NOT_FOUND when the resource declares no dispatchable operation under that identifier.\n */\nexport async function dispatchResourceOperationAsTool<TResult = any>(input: {\n ctx: FunctionToolExecutionContext;\n resourceType: ResourceType;\n /** A `CoreResourceOperation` member, or a custom operation identifier the resource declares. */\n operationIdentifier: string;\n /** The addressed row, for a row-scoped operation. Authorizes AND addresses; omit for a collection call. */\n recordId?: string;\n /** A filter addressing a COLLECTION, for a bulk operation. Never an authorization subject. */\n dispatchFilter?: any;\n /**\n * Parent / context resource ids used to build the scoped execution context, keyed by resource type\n * or field identifier. Omit for an operation the caller addresses with no parent scope — a\n * collection of an application-scoped resource.\n */\n contextIds?: Readonly<Record<string, string>>;\n /** The operation payload — the body for a write, the query options for a read. */\n data?: any;\n /** Repository options passed through, e.g. `{ paginated: true }` for a LIST envelope. */\n options?: any;\n}): Promise<TResult> {\n const { ctx, ...dispatch } = input;\n // #2666 S7: the tool plane's dispatch is the shared seam's, so a tool and a chat command cannot drift.\n return dispatchResourceOperationForPrincipal<TResult>({ plane: OperationDispatchPlane.AGENT_TOOL, principal: ctx, ...dispatch });\n}\n\n/**\n * The planes this seam serves (#2666 S7): every `OperationDispatchPlane` (`@wildo-ai/saas-models`) except MCP's\n * `tools/call` and the operation's own HTTP route (#2949), which count the declared policy on their own paths. MCP's reaches\n * the same gates through `McpServerBackendService.callTool`, as the plane table\n * on {@link assertDeclaredOperationRateLimit} records. Each plane counts its dispatches in a rate-limit bucket of its own\n * and names itself in its refusals (`OPERATION_DISPATCH_PLANE_FACTS`); everything else (the operation it may dispatch,\n * the context, authorization, the charge and the dispatch) is the one seam,\n * {@link prepareResourceOperationDispatchForPrincipal}.\n *\n * The vocabulary moved to `@wildo-ai/saas-models` for #3008, when the record of a declared-policy refusal started naming\n * the plane; this alias is what keeps the MCP and HTTP-route members out of the seam's entry points.\n */\nexport type ResourceOperationSeamPlane = Exclude<OperationDispatchPlane, OperationDispatchPlane.MCP_TOOL | OperationDispatchPlane.HTTP_ROUTE>;\n\n/**\n * Who a seam dispatch acts for: the principal's server-verified authority, the organization it acts in, and the services\n * the seam is built from. A {@link FunctionToolExecutionContext} is one; a chat command builds one from the linked member.\n */\nexport type ResourceOperationDispatchPrincipal = Pick<FunctionToolExecutionContext, 'auth' | 'organizationId' | 'services'>;\n\n/**\n * A resource operation resolved, scoped, authorized and charged for one principal, and not yet run (#2666 S7).\n *\n * Two phases because one plane must act between them: a chat command records that its run started (so a retry can never\n * run it twice) only after every refusal that can be decided in advance, and before the dispatch.\n */\nexport interface PreparedResourceOperationDispatch<TResult = any> {\n /** The URL-bearing default operation that will run. */\n readonly operation: ResourceConfiguration_Operation<any, any, any>;\n /** The context it runs in, built from the principal's verified authority for THIS operation. */\n readonly executionContext: ExecutionContext<any>;\n /**\n * Run it, once. The authorization and the charge covered one dispatch, so a second call refuses rather than running\n * the operation again on a budget spent once.\n */\n dispatch(data?: unknown, options?: unknown): Promise<TResult>;\n}\n\n/**\n * Prepare a resource operation dispatched on a principal's behalf off the HTTP route (#556, #2666 S7): resolve the\n * URL-bearing default, build the execution context from the principal's verified authority, authorize, then charge the\n * operation's declared budget in the plane's bucket. Every gate the service tier skips is applied here, in the order\n * {@link dispatchResourceOperationAsTool} documents, and nothing has run when it returns.\n *\n * assurance-control: WILDO.ACCESS.LEAST_PRIVILEGE — every plane that reaches a resource operation off the HTTP route is held\n * to that operation's own declared authority and budget, through this one seam.\n * assurance-control: WILDO.AI.AGENT_AUTHORITY_CONFINEMENT — an agent's tool dispatch is held to its principal's authority by the operation's own gates.\n *\n * @throws AUTHORIZATION when the operation's roles refuse the principal; RATE_LIMIT (429) when its budget is spent; an\n * Error naming the plane when the resource declares no URL-bearing default for the operation.\n */\nexport async function prepareResourceOperationDispatchForPrincipal<TResult = any>(input: {\n readonly plane: ResourceOperationSeamPlane;\n readonly principal: ResourceOperationDispatchPrincipal;\n readonly resourceType: ResourceType;\n /** A `CoreResourceOperation` member, or a custom operation identifier the resource declares. */\n readonly operationIdentifier: string;\n /** The addressed row, for a row-scoped operation. Authorizes AND addresses; omit for a collection call. */\n readonly recordId?: string;\n /** A filter addressing a COLLECTION, for a bulk operation. Never an authorization subject. */\n readonly dispatchFilter?: any;\n /** Parent / context resource ids the execution context is scoped by, keyed by resource type or field identifier. */\n readonly contextIds?: Readonly<Record<string, string>>;\n}): Promise<PreparedResourceOperationDispatch<TResult>> {\n const { plane, principal, resourceType, operationIdentifier, recordId, dispatchFilter, contextIds } = input;\n\n const operation = requireDispatchableOperation(principal, plane, resourceType, operationIdentifier);\n // Rebuild a scoped ExecutionContext from the PRINCIPAL's verified auth for THIS operation. Never\n // reuse one built for another operation: the scope it resolves is operation-specific.\n //\n // An omitted `contextIds` is an EMPTY scope map, never `undefined`. The field is optional because a\n // collection of an application-scoped resource has no parent to name, and `buildContextFromSocketAuth`\n // reads the map it is given (`Object.keys` on its first line, then the declared-scope filter). Passing\n // the absence through made the creation assistant's first real turn throw `Cannot convert undefined or\n // null to object` on every read of the workbench's own resources (2026-09-24, #1464) — while every pin\n // here stayed green, because the mocked creator ignored its third argument.\n const executionContext = await principal.services.executionContextCreator.buildContextFromSocketAuth(principal.auth, operation, { ...(contextIds ?? {}) });\n\n await authorizeToolDispatch(principal, executionContext, recordId);\n await assertDeclaredOperationRateLimit(principal, plane, operation, resourceType, operationIdentifier, executionContext);\n\n const operationPath = ResourcesConfig_OperationPathUtils.extractOperationPath(operation) as ResourceConfiguration_OperationPath<any, any>;\n const subject = recordId ?? dispatchFilter;\n let dispatched = false;\n\n return {\n operation,\n executionContext,\n dispatch: (data?: unknown, options?: unknown): Promise<TResult> => {\n if (dispatched) {\n return Promise.reject(new Error(`${OPERATION_DISPATCH_PLANE_FACTS[plane].callerLabel} for \"${resourceType}.${operationIdentifier}\": a prepared dispatch runs once.`));\n }\n dispatched = true;\n /*\n * The trailing `options` is OMITTED rather than passed as `undefined` when absent, so this seam\n * calls the dispatcher with exactly the arity each site used before it existed.\n *\n * Behaviourally the two are identical for an optional parameter. What differs is what a test can\n * see: the authorization and write pins here assert the dispatch with `toHaveBeenCalledWith`,\n * which is arity-exact, so a uniform five-argument call would have required editing four tests\n * that guard an authorization path. Preserving the shape proves the refactor changed nothing,\n * which is the property that matters most for the one seam every tool dispatch now goes through.\n */\n const result = options === undefined\n ? principal.services.servicesRegistryHandler.doByOperationPath(operationPath, executionContext, subject, data)\n : principal.services.servicesRegistryHandler.doByOperationPath(operationPath, executionContext, subject, data, options as RepositoryOptions);\n // #3369: the owners of the rows this dispatch returned, read from the RAW result before any tool projects it, recorded\n // into the tool call being observed (nothing outside an agent tool call). A row the tool returns without its\n // `organizationId` is then still attributed to the organization that owns it.\n return Promise.resolve(result).then((rows: TResult) => {\n // An unregistered resource counts as organization-owned, as the owner policy counts it (fail closed).\n const primaryScope = principal.services.resourcesRegistry.tryGetResourceConfiguration?.(resourceType)?.resourcePrimaryScope;\n observeDispatchedRecordOwners(resourceType, (primaryScope ?? ResourcePrimaryScope.ORGANIZATIONS) === ResourcePrimaryScope.ORGANIZATIONS, rows);\n return rows;\n });\n },\n };\n}\n\n/** {@link prepareResourceOperationDispatchForPrincipal}, then its dispatch, for a plane with nothing to do between them. */\nexport async function dispatchResourceOperationForPrincipal<TResult = any>(input: Parameters<typeof prepareResourceOperationDispatchForPrincipal>[0] & {\n /** The operation payload — the body for a write, the query options for a read. */\n readonly data?: unknown;\n /** Repository options passed through, e.g. `{ paginated: true }` for a LIST envelope, or an idempotency key. */\n readonly options?: unknown;\n}): Promise<TResult> {\n const { data, options, ...preparation } = input;\n const prepared = await prepareResourceOperationDispatchForPrincipal<TResult>(preparation);\n return prepared.dispatch(data, options);\n}\n\n/**\n * Is this a REFUSAL the read tool must never launder into a different operation?\n *\n * Exists for exactly one reason: the read tool's SEARCH branch degrades to a scoped LIST on any\n * throw, and a refusal swallowed there would silently become an UNGATED LIST — the guard present\n * and inert, which is worse than absent because it reads as enforced. Two refusal kinds qualify:\n *\n * - **RATE_LIMIT** — a declared budget is an application's statement about the endpoint, not a\n * reason to reach for a different one.\n * - **AUTHORIZATION** — stronger still. A denial has already been RECORDED by the authorizer's\n * audit funnel, so proceeding would leave a `RESOURCE_OPERATION_DENIED` row beside a request\n * that then succeeded, making the access trail describe something that did not happen.\n *\n * A genuine \"this resource has no URL-bearing SEARCH operation\" still degrades, unchanged.\n */\nfunction isNonDegradableRefusal(error: unknown): boolean {\n return isWildoBackendError(error)\n && (error.type === ErrorType.RATE_LIMIT || error.type === ErrorType.AUTHORIZATION);\n}\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.ask-person-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `askPersonTool` registers under unless told otherwise.\n */\nexport const ASK_PERSON_FUNCTION_REF = 'engine.ask-person';\n\n/**\n * A tool through which an agent pauses its turn to ask its person a structured question (#2720).\n *\n * The agent calls it with a title, a reason and its questions (each a free_text, a choice or a yes/no). The turn\n * pauses, and the person in the conversation is shown the questions through a form: the engine has a model lay them\n * out (an amount as an amount, a day as a day, groups under headings) and asks them through the automated form, in the\n * chat and in the decision inbox. The person sends the answers, which the tool returns to the agent as\n * `{ answers: { [ref]: value }, comment? }` (`humanDecisionAgentValues`: an amount as `{ amount: \"19.99\", currency }`, a\n * day as `YYYY-MM-DD`, a moment as an ISO 8601 instant, a range as `{ from, to }`, and `comment` when the person added\n * a note), or declines, and the agent is told to decide on its own.\n *\n * Register it on a backend module's `flowsActors.functionTools` and grant it to an agent by its ref\n * (`capabilities.tools.functionRefs`). Only a turn with a person in it can ask: the question is routed to the turn's\n * owner, and an autonomous turn has none, so its call is refused at once as nobody can answer it — as is any approval\n * routed to the owner of such a turn.\n *\n * Two options adapt it to a host: `composesForm: false` asks the questions through the default form exactly as written\n * (for questions that invite free answers a typed control would refuse), and `declinedReason` replaces what the agent\n * is told when the person declines.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [askPersonTool()] }\n * // the agent: capabilities: { tools: { functionRefs: [ASK_PERSON_FUNCTION_REF] } }\n */\nexport function askPersonTool(options?: {\n functionRef?: string;\n description?: string;\n /** `false` asks the questions through the default form, as written. See {@link FunctionTool.composesQuestionForm}. */\n composesForm?: boolean;\n /** What the agent is told when the person declines. See {@link FunctionTool.questionDeclinedReason}. */\n declinedReason?: string;\n}): FunctionTool {\n return {\n functionRef: options?.functionRef ?? ASK_PERSON_FUNCTION_REF,\n description: options?.description\n ?? 'Ask the person you are working with one or more questions, and wait for their answers. Use it when you need '\n + 'information only they have, or a choice only they can make, before you can go on. Ask for what you need in one '\n + 'call, and do not ask for anything you can find yourself. It returns { answers, comment }: each answer under its '\n + 'question\\'s ref (an amount as { amount, currency } with the amount in the currency\\'s main unit, e.g. \"19.99\"; a '\n + 'day as YYYY-MM-DD; a moment as an ISO 8601 instant; a range as { from, to }), and comment when the person added '\n + 'a note.',\n inputSchema: AskPerson_ToolInputSchema,\n requiresHumanApproval: true,\n asksThePerson: true,\n ...(options?.composesForm === false ? { composesQuestionForm: false } : {}),\n ...(options?.declinedReason ? { questionDeclinedReason: options.declinedReason } : {}),\n effect: FunctionToolEffect.READ,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS, reason: 'It returns the answer the person chose to give.' },\n authority: { kind: FunctionToolAuthorityKind.NO_APPLICATION_DATA, reason: 'It asks the person and returns their answer; it reads and writes no record.' },\n returnsThePersonsOwnWords: true,\n execute: async (args) => {\n // Reached only after the person answered: answering replaces `answers` with their values, and declining does\n // not run the tool. A call that arrives without them is refused rather than answered with nothing.\n const input = AskPerson_ToolInputSchema.parse(args);\n if (!input.answers) throw new Error('The person has not answered this question.');\n return { answers: input.answers, ...(input.comment ? { comment: input.comment } : {}) };\n },\n };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.ask-person-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.present-records-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `presentRecordsTool` registers under unless told otherwise.\n */\nexport const PRESENT_RECORDS_FUNCTION_REF = 'engine.present-records';\n\n/**\n * A tool through which an agent SHOWS its person the records it is talking about, in the conversation.\n *\n * The agent calls it with a resource type, the ids a read or write tool returned, and the view (`summary`, one card per\n * record). The conversation draws the call as those records' summary cards, with the turn's other work, above its reply.\n * Use it when a list of records says more than a sentence: the todos due this week, the record the agent just created\n * or changed, the candidates it is asking about.\n *\n * Only a reference is kept. The transcript stores a tool call's input and never its result, so the ids are what\n * survives a reload. The browser fetches each record with the viewer's own session whenever it draws the conversation,\n * in the organization the tool read in: a record the viewer cannot read shows as unavailable, and a card shows the\n * record as it was when the conversation was drawn, so a record changed later shows its change on the next draw (the\n * default description tells the agent to show a record again after changing it). A card opens its record when the\n * resource has a page in the application within the viewer's tenancy; otherwise it is drawn without a link.\n *\n * The tool reads each record as the person first, through the resource's own READ operation and its access rules, and\n * tells the agent which records the person sees (`shown`) and which they could not be shown (`unavailable`: missing,\n * or out of their reach, which answer alike). Any other refusal (the operation's roles, a rate limit, a fault) fails the\n * whole call.\n *\n * The tool's result is never stored, so the cards add no copy of a record to the requester's transcript. The agent's\n * reply is stored like any reply, and it names the records it shows.\n *\n * Offered only to a turn a person watches in a conversation the application draws: an external agent over A2A\n * receives the reply's text and no tool calls, and an autonomous turn has nobody watching, so neither is offered it\n * (`isFunctionToolOfferedToTurn`). On a later turn the agent does not see which records it showed (a turn replays the\n * conversation's text only), so it reads a record again before acting on it.\n *\n * `resourceTypes` are the resources the agent may show. Grant only resources it can already read. Each needs a READ\n * operation reachable over HTTP, and its summary is the resource's authored summary layout, else the engine's default\n * from its summary fields.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [presentRecordsTool({ resourceTypes: ['todos', 'todoLists'] })] }\n * // the agent: capabilities: { tools: { functionRefs: [PRESENT_RECORDS_FUNCTION_REF] } }\n */\nexport function presentRecordsTool(options: {\n resourceTypes: readonly [ResourceType, ...ResourceType[]];\n functionRef?: string;\n description?: string;\n}): FunctionTool {\n const resourceTypes = [...new Set(options.resourceTypes)] as [ResourceType, ...ResourceType[]];\n return {\n functionRef: options.functionRef ?? PRESENT_RECORDS_FUNCTION_REF,\n description: options.description\n ?? 'Show the person records you are talking about, as cards in the conversation: the records a question is about, '\n + 'what you just created or changed, or a short list they asked for. Pass the ids exactly as a read or write tool '\n + 'returned them, each once. The cards are drawn above your reply, so refer to them as above, name each record you show, and '\n + 'do not repeat the fields the cards carry. A card shows the record as it is when the conversation is drawn: '\n + 'after you change a record you showed, show it again. On a later turn, read a record again before acting on it. '\n + 'It returns { shown, unavailable }: tell the person when a record could not be shown.',\n inputSchema: PresentRecords_ToolInputSchema.extend({\n resourceType: z.enum(resourceTypes).describe('The kind of record to show.'),\n }),\n effect: FunctionToolEffect.READ,\n presentsRecords: true,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.NOT_FROM_RECORDS, reason: 'It returns which record ids were shown or unavailable, never their fields.' },\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n execute: async (args: PresentRecords_ToolInput, ctx: FunctionToolExecutionContext): Promise<PresentRecords_ToolResult> => {\n const input = PresentRecords_ToolInputSchema.parse(args);\n if (!resourceTypes.includes(input.resourceType as ResourceType)) {\n throw new Error(`This tool shows only ${resourceTypes.join(', ')} records.`);\n }\n const resourceType = input.resourceType as ResourceType;\n // A resource exposing no URL-bearing READ cannot be drawn by the browser either: a refusal naming the operation,\n // never \"unavailable\".\n requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.READ);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n const readable = await Promise.all(input.ids.map(async (id) => {\n try {\n const record = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: CoreResourceOperation.READ, recordId: id, contextIds });\n return record !== null && record !== undefined;\n } catch (error) {\n // A missing row and a row out of the person's reach both answer NOT_FOUND on the row path, alike by design\n // (as `resourceReadTool`). Every other refusal (the operation's roles, a rate limit) fails the call.\n if (isWildoBackendError(error) && error.type === ErrorType.NOT_FOUND) return false;\n throw error;\n }\n }));\n return {\n shown: input.ids.filter((_id, index) => readable[index]),\n unavailable: input.ids.filter((_id, index) => !readable[index]),\n };\n },\n };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.present-records-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.retrieval-tool facet:layer:backend facet:family:flows-actors facet:audience:app-developer\n *\n * The ref `retrievalTool` registers under unless told otherwise.\n */\nexport const RETRIEVAL_FUNCTION_REF = 'engine.retrieve';\n\n/** What the agent sends: a question in its own words, and how many records it wants back at most. */\nexport const Retrieval_ToolInputSchema = z.object({\n query: z.string().trim().min(1).max(1000).describe('What to look for, in plain words: the question, or the facts you need.'),\n limit: z.number().int().min(1).max(20).optional().describe('The most matching passages to look at (default 8); several may come from one record.'),\n});\nexport type Retrieval_ToolInput = z.infer<typeof Retrieval_ToolInputSchema>;\n\n/**\n * How a search ENDED, which is what the agent must act on before it answers, and why this is not a boolean on whether\n * results came back. Only a healthy, unobstructed search may say \"nothing matched\": a refused, failed, unrun or\n * incomplete search has proved nothing about whether the information exists (#2300, carried over from the Wonder Todos\n * knowledge-base tool that had to write this for itself).\n */\nexport enum RetrievalToolOutcome {\n /** Quotable passages came back. `notes` may still qualify how much was covered. */\n MATCHED = 'matched',\n /** A healthy search found nothing, and no refusal or failed read obscured it. */\n NOTHING_MATCHED = 'nothing-matched',\n /** Sources were not admitted for this caller: nothing is known about whether the information exists. */\n REFUSED = 'refused',\n /** The search failed or could not run. */\n UNAVAILABLE = 'unavailable',\n /** Nothing usable came back from a search or a read stage that did not complete. */\n INCOMPLETE = 'incomplete',\n}\n\n/**\n * What the tool returns. Each result is one record, with the passages that matched, each naming the field it came from:\n * that pair (record, field) is the citation. `notSearched` names every source the caller could not search, and `notes`\n * says, in words the agent can repeat, everything that made the answer smaller than the index could support.\n */\nexport interface Retrieval_ToolResult {\n outcome: RetrievalToolOutcome;\n results: Array<{\n resourceType: ResourceType;\n recordId: string;\n /** The record's name, as the resource's summary describes it. */\n title: string;\n excerpts: Array<{ field: string; text: string }>;\n }>;\n notSearched: Array<{ resourceType: ResourceType; reason: string }>;\n notes: string[];\n searchStatus: RagRetrievalSearchStatus;\n embeddingStatus: RagRetrievalEmbeddingStatus;\n}\n\n/**\n * What `retrievalTool` tells the model, unless told otherwise. Exported so an application can ADD what its sources are\n * for (`${RETRIEVAL_TOOL_DESCRIPTION} Use it for questions about our policies.`) without losing how to read the outcome.\n */\nexport const RETRIEVAL_TOOL_DESCRIPTION =\n 'Search the application\\'s own documents and records for what you need to answer. Ask in your own words, as a '\n + 'focused question, not the person\\'s message pasted in. Read `outcome` before you answer. \"matched\": answer only '\n + 'from the returned passages, and say which record (title) each fact came from. \"nothing-matched\": a healthy search '\n + 'found nothing; say so, and do not answer from general knowledge as if it were grounded. \"refused\", \"unavailable\" or '\n + '\"incomplete\": you have learned nothing about whether the information exists; never report it as absent. `notes` '\n + 'says what made the answer incomplete, and `notSearched` the sources you may not search.';\n\n/**\n * A tool through which an agent answers from the application's own documents and records: it searches the retrieval\n * index (every field declared `.ragSource()`, files included) and returns the matching passages with what they came\n * from, so the agent can quote and cite them.\n *\n * It searches only the `resourceTypes` you name, each of which must declare a `.ragSource()` field (startup refuses one\n * that does not). It searches as the CALLER: a source whose READ operation the caller's roles refuse is not searched\n * and is named in `notSearched`, and a matching record the caller cannot read is dropped. So an agent can never quote\n * a document its person could not open. It only reads, so it is offered on every turn, including an autonomous turn\n * started by an inbound message; what it returns came from your own records and is still content, not instructions.\n *\n * The search's query embedding is charged to the turn's case and run like the turn's own model calls, and every row\n * it reads is attributed to the agent, as for any tool.\n *\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @example\n * // backend-api/src/modules/<module>/index.ts\n * flowsActors: { functionTools: [retrievalTool({ resourceTypes: ['knowledgeDocuments'] })] }\n * // the agent: capabilities: { tools: { functionRefs: [RETRIEVAL_FUNCTION_REF] } }\n */\nexport function retrievalTool(options: {\n resourceTypes: readonly [ResourceType, ...ResourceType[]];\n functionRef?: string;\n description?: string;\n /** Characters of matched text returned per call (the retrieval service's own default when absent). */\n maxContextCharacters?: number;\n}): FunctionTool {\n const resourceTypes = [...new Set(options.resourceTypes)] as [ResourceType, ...ResourceType[]];\n return {\n functionRef: options.functionRef ?? RETRIEVAL_FUNCTION_REF,\n description: options.description ?? RETRIEVAL_TOOL_DESCRIPTION,\n inputSchema: Retrieval_ToolInputSchema,\n effect: FunctionToolEffect.READ,\n retrievalSources: resourceTypes,\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.TREATED_BY_TOOL, treat: treatRetrievalToolResult },\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_SCOPED_SERVICE, reason: \"It searches the retrieval index with a context built from the caller's own auth, so only records the caller may read are returned.\" },\n execute: async (args: Retrieval_ToolInput, ctx: FunctionToolExecutionContext): Promise<Retrieval_ToolResult> => {\n const input = Retrieval_ToolInputSchema.parse(args);\n const retrieval = ctx.services.ragRetrieval;\n if (!retrieval) throw new Error('Searching documents is not available here.');\n // The caller's own authority, built from their verified auth on the READ of a declared source, exactly as a read\n // tool builds it. Retrieval derives each source's own READ context from it and applies its three gates; it takes\n // no tenancy argument, so this context is the only authority the search has.\n const operation = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceTypes[0], CoreResourceOperation.READ);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n const executionContext = await ctx.services.executionContextCreator.buildContextFromSocketAuth(ctx.auth, operation, contextIds);\n const result = await retrieval.retrieve({\n query: input.query,\n executionContext,\n resourceTypes,\n limit: input.limit ?? 8,\n ...(options.maxContextCharacters ? { maxContextCharacters: options.maxContextCharacters } : {}),\n });\n return retrievalToolResultOf(result);\n },\n };\n}\n\n/**\n * A retrieval result as a guarded agent's model may read it (#2292): a passage of a personal field is withheld whole, and\n * a record's title is reduced to the resource's name when the title is built from a personal summary field. The\n * citation (record id, field name) stays, so the agent can still say where an answer came from.\n */\nfunction treatRetrievalToolResult(output: unknown, guard: PersonalDataGuard): unknown {\n const result = output as Retrieval_ToolResult;\n if (!result || !Array.isArray(result.results)) return output;\n return {\n ...result,\n results: result.results.map((row) => {\n const personal = guard.personalFieldsOf(row.resourceType);\n const title = guard.summaryCarriesPersonalData(row.resourceType) ? (row.title.split(' — ')[0] ?? row.title) : row.title;\n return {\n ...row,\n title,\n excerpts: row.excerpts.map((excerpt) => {\n const categories = personal.get(excerpt.field);\n return categories === undefined ? excerpt : { ...excerpt, text: guard.withholdPassage(categories) };\n }),\n };\n }),\n };\n}\n\n/**\n * The agent's view of a retrieval: the records and their cited passages, how the search ended, and every reason the answer\n * is smaller than the index could support. Search health always passes through, so an empty result never reads as a\n * proof of absence on its own.\n */\nexport function retrievalToolResultOf(result: RagRetrievalResult): Retrieval_ToolResult {\n const results = result.rows.map((row) => ({\n resourceType: row.resourceType,\n recordId: row.resourceId,\n title: row.header,\n excerpts: row.passages.map((passage) => ({ field: passage.fieldName, text: passage.text })),\n }));\n const notSearched = result.refusedResourceTypes.map((refusal) => ({ resourceType: refusal.resourceType, reason: refusal.reason }));\n const { truncation } = result;\n const notes: string[] = [];\n let outcome: RetrievalToolOutcome;\n if (result.searchStatus === RagRetrievalSearchStatus.FAILED) {\n outcome = RetrievalToolOutcome.UNAVAILABLE;\n notes.push('The search failed. Do not claim the information does not exist; report the search as unavailable.');\n } else if (result.searchStatus === RagRetrievalSearchStatus.NOT_RUN) {\n outcome = notSearched.length > 0 ? RetrievalToolOutcome.REFUSED : RetrievalToolOutcome.UNAVAILABLE;\n notes.push('No search ran. Nothing has been learned about whether the information exists.');\n } else if (results.length > 0) {\n outcome = RetrievalToolOutcome.MATCHED;\n } else if (result.searchStatus === RagRetrievalSearchStatus.DEGRADED || result.embeddingStatus === RagRetrievalEmbeddingStatus.FAILED\n || result.embeddingStatus === RagRetrievalEmbeddingStatus.CEILING_REFUSED\n || truncation.droppedByReadFailure > 0 || truncation.droppedUnreadableRows > 0) {\n outcome = RetrievalToolOutcome.INCOMPLETE;\n notes.push('Nothing readable came back from an incomplete search. Do not infer that the information is absent.');\n } else if (notSearched.length > 0) {\n outcome = RetrievalToolOutcome.REFUSED;\n notes.push('Some sources could not be searched for this person. Do not infer that the information is absent.');\n } else {\n outcome = RetrievalToolOutcome.NOTHING_MATCHED;\n notes.push('The search found no match. Say so; do not answer from general knowledge.');\n }\n if (result.searchStatus === RagRetrievalSearchStatus.DEGRADED) notes.push('Some search paths were unavailable. Use what came back, but describe the search as incomplete.');\n if (result.embeddingStatus === RagRetrievalEmbeddingStatus.FAILED) notes.push('The search by meaning failed; only the search by wording ran, so coverage is incomplete.');\n // #3030: a plan's limit, not an outage, and worded so: the model should not report the search as broken.\n if (result.embeddingStatus === RagRetrievalEmbeddingStatus.CEILING_REFUSED) notes.push('The organization\\'s allowance for search by meaning is used up for this period; only the search by wording ran, so coverage is incomplete.');\n if (notSearched.length > 0 && results.length > 0) notes.push('Some sources could not be searched; the passages returned do not cover them.');\n if (truncation.droppedUnreadableRows > 0) notes.push(`${truncation.droppedUnreadableRows} matching record(s) were withheld because this person may not read them. Do not try to reach them another way.`);\n if (truncation.droppedByReadFailure > 0) notes.push(`${truncation.droppedByReadFailure} record read(s) failed. This is an operational failure, not a permission decision; the answer is incomplete.`);\n if (truncation.reachedHitLimit || truncation.reachedContextCharacterBudget) notes.push('More may match than was returned. A narrower question may find the rest.');\n return { outcome, results, notSearched, notes, searchStatus: result.searchStatus, embeddingStatus: result.embeddingStatus };\n}\n/** @wildo_source:part:end saas.backend.flows-actors.retrieval-tool */\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.resource-read-tool facet:layer:backend facet:family:flows-actors\n *\n * Generic resource-read tool factory. Produces a {@link FunctionTool} that lets\n * an agent look up records of ONE resource type **scoped to the calling user**,\n * with that user's own visibility — no `systemAccessPolicy` bypass. Instantiate\n * it per resource an agent should be able to read (e.g. `resourceReadTool(TODOS)`),\n * making any registered resource agent-readable without hand-writing a tool.\n *\n * The tool dispatches the resource's PUBLIC, URL-bearing default LIST / SEARCH — the same\n * operation a REST client reaches — under a user `ExecutionContext` rebuilt from the caller's\n * socket auth, and applies that operation's own declared `roles` ACL through\n * `AuthorizationsBackendService.authorizeInController` before dispatching it. So the framework's\n * contextual filter AND the role ACL apply exactly as for the user's own request. (The role gate\n * is named explicitly because it does NOT come free with the service path: the service tier\n * applies tenancy and the operation pipeline and no role check, so a tool that merely dispatched\n * would run with the ACL unread — which is what this factory did until 2026-09-08.) A resource\n * that declares no URL-bearing default for the operation is REFUSED rather than served through its\n * route-less internal variant. WHO the caller is is NEVER taken\n * from the model — only the record `id`, `searchQuery`, `filters` and `limit` args are. Its `functionRef`\n * defaults to `resource.<resourceType>.read` — reference that exact string from\n * your agent's `capabilities.tools.functionRefs`. Import path:\n * `@wildo-ai/saas-backend-lib`.\n *\n * **Looking up one record by its id.** Pass `id` to read ONE record through the resource's\n * URL-bearing default READ — the same operation a REST client reaches — authorized as a row\n * call under the same role ACL and contextual filter. A record that does not exist and a record\n * the caller may not see both answer an empty `data`, deliberately alike, so a lookup never tells\n * a caller that a record they cannot see exists. When `id` is given, `searchQuery` is ignored.\n * A `searchQuery` matches a resource's searchable TEXT and never an id: an agent told to\n * \"resolve the id\" of a record the user already identified by id must pass it as `id`, because a\n * search for an id finds nothing and reads, to the model and then to the user, as \"no such\n * record\". A resource that declares no URL-bearing READ is refused, as for any operation it does\n * not expose.\n *\n * **Narrowing by a field's value.** The tool also offers `filters`: the filter fields the resource's\n * default SEARCH declares (else its LIST), each as it accepts values — one of an enum's values, a\n * string, a number, a boolean, or a `{ startDate, endDate }` / `{ min, max }` / `{ startMonth, endMonth }` range. They are bound\n * when the tool is registered, from the operation it dispatches, so the model is offered what that\n * operation's repository allows — less the primary scope's field (`organizationId`), which the\n * conversation's own context decides. A question about a status or a category is a filter, never a\n * `searchQuery`: a search for the word \"pending\" matches no title. Filters work with or without a\n * `searchQuery`, and a resource that declares none offers none. A calendar-day `endDate` includes\n * that whole day (UTC). The result's `truncated` says more records matched than came back.\n * `searchQuery` itself is offered only when the resource's SEARCH can take a text (`isSearchable`\n * with `searchableFields`); when a search fails at run time, the answer is the filtered list and\n * says `searchQueryNotApplied`, so it is never read as what the text found.\n *\n * @param resourceType the resource to expose (any registered `ResourceType`).\n * @param options optional `functionRef` / `description` / `defaultLimit` / `maxLimit` overrides.\n * @example\n * // in a backend module's `flowsActors.functionTools` contribution:\n * functionTools: [resourceReadTool(TasksManager_ResourceType.TODOS)]\n * // and on the agent:\n * capabilities: { tools: { functionRefs: ['resource.todos.read'], mcpRefs: [] } }\n */\nexport function resourceReadTool(\n resourceType: ResourceType,\n options?: { functionRef?: string; description?: string; defaultLimit?: number; maxLimit?: number },\n): FunctionTool {\n /** @wildo_source:part:end saas.backend.flows-actors.resource-read-tool */\n const defaultLimit = options?.defaultLimit ?? 50;\n const maxLimit = options?.maxLimit ?? 100;\n const lookUp = `Look up the \"${resourceType}\" records the current user may see, to answer their questions about them. `\n + `Pass \"id\" to fetch ONE record by its id.`;\n const onlyVisible = ` Only records the current user may see are ever returned.`;\n const description = options?.description ??\n `${lookUp} Otherwise optionally pass a free-text searchQuery, which matches record text and never an id.${onlyVisible}`;\n const baseShape = {\n id: z.string().min(1).optional()\n .describe('The id of ONE record to fetch. Use it whenever a record id is already known: no other argument matches an id.'),\n searchQuery: z.string().optional()\n .describe('Free text matched against the records\\' text (titles, descriptions). It never matches a status, a category or an id: to narrow by a field\\'s value, use filters.'),\n limit: z.number().int().min(1).max(maxLimit).optional(),\n };\n\n return {\n functionRef: options?.functionRef ?? `resource.${resourceType}.read`,\n effect: FunctionToolEffect.READ,\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE, resourceType },\n description,\n inputSchema: z.object(baseShape),\n /*\n * The filters this resource DECLARES, offered as an argument. Without them a model asked for \"my pending todos\" had\n * one tool for one question — free text — and searched for the word \"pending\" (which matches no title), found\n * nothing, then listed everything. Measured on Wonder Todos, 2026-10-09: two calls, `{\"searchQuery\":\"pending\"}` then\n * `{}`. The search operation already declares `status` among its filters, and the MCP door already advertises them.\n *\n * Bound from the operation this tool DISPATCHES when filtering (the default SEARCH, else LIST), by the same rule its\n * dispatch resolves it, so the fields offered are the fields that operation's repository allows, less the primary\n * scope field the conversation's own context decides. A resource that declares no filter keeps the base schema.\n */\n bindToResources: (resources) => {\n const search = resources.dispatchableOperationOf(resourceType, CoreResourceOperation.SEARCH);\n const operation = search ?? resources.dispatchableOperationOf(resourceType, CoreResourceOperation.LIST);\n const fields = readToolFilterFieldsOf(operation, resources.primaryScopeFieldOf(resourceType));\n const hasFilters = Object.keys(fields).length > 0;\n // A text to search is offered only when the operation it reaches can search text (#2769): authorize ≡ advertise\n // ≡ execute. Both repositories refuse a term on a SEARCH that is not `isSearchable` with `searchableFields`, so\n // offering one there could only ever be refused, then answered by a LIST that cannot apply it.\n const searchesText = readToolSearchesText(search);\n if (searchesText && !hasFilters) return undefined;\n const { searchQuery: _textSearch, ...withoutSearch } = baseShape;\n const shape = searchesText ? baseShape : withoutSearch;\n const fieldList = Object.entries(fields).map(([key, schema]) => describeReadToolFilterField(key, schema)).join('; ');\n const filterWords = hasFilters\n ? ` To find records by a field's value (a status, a category, a date range), pass filters${searchesText ? ' rather than a searchQuery' : ''}. Filterable: ${fieldList}.`\n : '';\n // An author's own description is kept as written; only the framework's says what the tool takes.\n const baseDescription = options?.description ?? (searchesText ? description : `${lookUp} These records cannot be searched by text.${onlyVisible}`);\n // Without a text search the schema is STRICT: a `searchQuery` sent anyway comes back to the model as an invalid\n // input it can correct, instead of being stripped and answered with every record (#2769).\n const objectOf = searchesText ? z.object : z.strictObject;\n return {\n inputSchema: objectOf({\n ...shape,\n ...(hasFilters ? {\n filters: z.strictObject(fields).optional()\n .describe(`Narrow to records whose fields have these values.${searchesText ? ' Combine with searchQuery or use alone.' : ''} Fields: ${fieldList}.`),\n } : {}),\n }),\n description: `${baseDescription}${filterWords}`,\n };\n },\n execute: async (args: { id?: string; searchQuery?: string; limit?: number; filters?: Record<string, unknown> }, ctx: FunctionToolExecutionContext): Promise<ResourceReadToolResult> => {\n const { servicesRegistryHandler, executionContextCreator } = ctx.services;\n const limit = typeof args?.limit === 'number' ? Math.min(args.limit, maxLimit) : defaultLimit;\n const searchQuery = typeof args?.searchQuery === 'string' && args.searchQuery.trim().length > 0 ? args.searchQuery.trim() : undefined;\n const filter = readToolFilterOf(args?.filters);\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n\n /*\n * IDENTITY LOOKUP (#1038). This tool used to offer only SEARCH and LIST, and SEARCH matches a resource's\n * searchable TEXT. So an agent told to \"resolve its id with the read tool\" — the Todo Assistant's own\n * instruction — searched for an id, found nothing, and told its user that a record which existed did not.\n * Measured 2026-09-14: the same seeded row was returned by LIST and by a SEARCH on its title, and by a\n * SEARCH on its id not at all.\n *\n * READ is the operation that answers \"this record, by id\", so an id is dispatched there: a ROW call, with\n * the id as the authorization subject, under the operation's own role ACL and contextual filter — the same\n * seam UPDATE uses.\n */\n const id = typeof args?.id === 'string' && args.id.trim().length > 0 ? args.id.trim() : undefined;\n if (id) {\n // Outside the catch below on purpose: a resource exposing no URL-bearing READ is a refusal naming the\n // operation, and must never be read as \"not found\".\n const readOp = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.READ);\n let record: unknown;\n try {\n record = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.READ,\n recordId: id,\n contextIds,\n });\n } catch (error) {\n // A missing row and a row outside the caller's reach both answer NOT_FOUND on the row path, alike by\n // design. Both become an empty result, so the model can say \"no such record visible to you\" instead of\n // reporting a failure — and nothing distinguishes the two. Every other refusal (AUTHORIZATION from the\n // operation's roles, RATE_LIMIT) propagates unchanged.\n if (isWildoBackendError(error) && error.type === ErrorType.NOT_FOUND) return { data: [] };\n throw error;\n }\n if (record === null || record === undefined) return { data: [] };\n return { data: [await toResponseSafeToolOutput(readOp, record)] };\n }\n\n // Prefer SEARCH when a query or a filter is supplied AND the resource EXPOSES it (a search with no term and a filter\n // is the filter-only search the collection views run); fall back to a scoped LIST, which carries the same filter.\n // Both run as the user, under the operation's own role ACL (no bypass).\n if (searchQuery || filter) {\n // The fallback catch covers ONLY op-resolution + the search call — a resource may expose no\n // SEARCH operation, in which case we degrade to a scoped LIST. It deliberately does NOT wrap\n // the response-DTO projection below: a projection failure there is a real server contract\n // violation (a record that violates its own response DTO) and must surface as a tool error,\n // exactly as it would on the LIST path — never silently degrade to an unfiltered LIST.\n let searchOp: ResourceConfiguration_Operation<any, any, any> | undefined;\n let searchResult: unknown;\n try {\n // Non-throwing: a resource with no URL-bearing SEARCH default has nothing to expose here,\n // which is the documented degradation rather than a refusal.\n searchOp = resolveDispatchableOperation(ctx, resourceType, CoreResourceOperation.SEARCH);\n if (searchOp) {\n // The seam authorizes, charges and dispatches in that order. It sits inside this try\n // because that is where the dispatch is; the catch below re-throws either refusal so\n // neither can be laundered into an ungated LIST. The operation is resolved twice — once\n // above to decide whether SEARCH is even available, once inside the seam — and that is\n // deliberate: the availability question is this factory's, the gates are the seam's.\n searchResult = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.SEARCH,\n contextIds,\n data: { searchQuery: searchQuery ?? '', filter, page: 1, limit },\n });\n }\n } catch (error) {\n // A declared budget, or a role refusal, is a statement about THIS endpoint — not a reason\n // to reach for a different one. Degrading here would answer the model with LIST results\n // the caller was just refused: enforcement that reports success.\n if (isNonDegradableRefusal(error)) throw error;\n searchOp = undefined; // SEARCH failed to resolve or dispatch — fall through to LIST.\n }\n if (searchOp !== undefined) {\n // Project through the SEARCH operation's response DTO + JSON wire step, exactly as the\n // REST controller does, so no `Date`/backend-only/secret field reaches the model.\n const safeSearchResult = await toResponseSafeToolOutput(searchOp, searchResult);\n return toReadResult(safeSearchResult, limit);\n }\n }\n\n // LIST is a distinct operation with its own ACL and its own declared budget, so it is\n // authorized and charged separately. A call that resolved SEARCH and then degraded to LIST\n // does both twice — two operations were attempted, exactly as two HTTP requests would be, and\n // that path is only reached when the search dispatch failed for a reason that is not a refusal.\n const listOp = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, CoreResourceOperation.LIST);\n // `paginated: true` yields the `{ data, pagination }` envelope the LIST response DTO expects\n // (the same shape the HTTP controller requests) — a bare array would fail the wrapper-DTO\n // projection in `toResponseSafeToolOutput` below.\n const listResult = await dispatchResourceOperationAsTool({\n ctx,\n resourceType,\n operationIdentifier: CoreResourceOperation.LIST,\n contextIds,\n // The filter rides LIST too: a failed SEARCH must never degrade into the UNFILTERED collection, which the model\n // would then report as the answer to the narrower question it asked.\n data: { filter, page: 1, limit },\n options: { paginated: true },\n });\n const safeListResult = await toResponseSafeToolOutput(listOp, listResult);\n const listed = toReadResult(safeListResult, limit);\n // A term reaches this LIST only when its SEARCH could not run, and LIST cannot apply it: say so rather than let\n // every record the filters allow read as what the text found (#2769).\n return searchQuery ? { ...listed, searchQueryNotApplied: true, note: SEARCH_QUERY_NOT_APPLIED_NOTE } : listed;\n },\n };\n}\n\n/**\n * @wildo_source:part:start saas.backend.flows-actors.resource-write-tool facet:layer:backend facet:family:flows-actors\n *\n * Generic resource-WRITE tool factory. The mutating sibling of {@link resourceReadTool}.\n * Produces a {@link FunctionTool} that lets an agent CREATE or UPDATE ONE resource\n * type **as the calling user**, under the caller's own `ExecutionContext` rebuilt\n * from their verified socket auth — no `systemAccessPolicy` bypass, and identity is\n * NEVER taken from the model. It dispatches the resource's PUBLIC, URL-bearing default CREATE /\n * UPDATE — the same operation a REST client reaches, with the same request DTO validating the\n * model's arguments and the same prefix / postfix side effects — and applies that operation's own\n * `accessControl` (roles + parent scope, plus per-row access on UPDATE) through\n * `AuthorizationsBackendService.authorizeInController` before the write. Authorization is therefore\n * **fail-closed**: a caller lacking the operation's role gets a thrown authz error, not a silent\n * write.\n *\n * Both halves of that are load-bearing and neither came free, so do not simplify them away. The\n * service tier applies tenancy and the operation pipeline and NO role check, and the service\n * layer's own default resolver PREFERS a route-less `INTERNAL_CALL` variant over the public one —\n * so before 2026-09-08 this factory dispatched a different operation from the one it advertises,\n * with the ACL unread. On `organizations` CREATE that combination created ownerless tenants.\n *\n * A resource that declares no URL-bearing default for the operation is REFUSED rather than written\n * through its internal variant. Owner FKs and other server-set fields are EC-injected / `excludeFromCreate`,\n * so the model can never spoof ownership through the tool arguments.\n *\n * **Retries.** A model calls a write tool again when a call fails, so an operation that declares\n * `idempotencyKey` takes the key as the `idempotencyKey` ARGUMENT: add\n * `idempotencyKey: z.string().describe(IDEMPOTENCY_KEY_TOOL_ARGUMENT_DESCRIPTION)` to `inputSchema` (`.optional()` for an\n * `ACCEPTED` operation). The factory takes it out of the fields and the framework answers the model's retry\n * with the first result instead of writing twice. A `REQUIRED` operation called without it is refused before\n * anything runs, naming the argument.\n *\n * Unlike the read tool (whose args are a fixed `{ searchQuery, limit }`), a write\n * tool's arguments are resource-specific, so the caller MUST supply the model-facing\n * `inputSchema` — the create/update field contract shown to the model. Keep it to the\n * fields the model should legitimately set. For `UPDATE`, include the record `id` in\n * the schema; the factory splits `id` out to address the row and passes the remaining\n * fields as the patch.\n *\n * `functionRef` defaults to `resource.<resourceType>.<op>` (e.g. `resource.todos.create`)\n * — reference that exact string from your agent's `capabilities.tools.functionRefs`.\n * Import path: `@wildo-ai/saas-backend-lib`.\n *\n * @param resourceType the resource to expose (any registered `ResourceType`).\n * @param op `CoreResourceOperation.CREATE` or `CoreResourceOperation.UPDATE`.\n * @param options `{ inputSchema, functionRef?, description? }` — `inputSchema` is REQUIRED (the model-facing argument contract).\n * @example\n * // in a backend module's `flowsActors.functionTools` contribution:\n * functionTools: [\n * resourceWriteTool(TasksManager_ResourceType.TODOS, CoreResourceOperation.CREATE, {\n * inputSchema: z.object({ title: z.string(), todoListId: z.string(), description: z.string().optional() }),\n * }),\n * ]\n * // and on the agent:\n * capabilities: { tools: { functionRefs: ['resource.todos.create'], mcpRefs: [] } }\n */\nexport function resourceWriteTool(\n resourceType: ResourceType,\n op: CoreResourceOperation.CREATE | CoreResourceOperation.UPDATE,\n options: {\n inputSchema: z.ZodTypeAny;\n functionRef?: string;\n description?: string;\n /**\n * Gate this write behind a HUMAN decision (see {@link FunctionTool.requiresHumanApproval}).\n *\n * Without this passthrough the flag was declarable only by hand-rolling a `FunctionTool`, so\n * the approval gate was unreachable from the factory every app author actually uses — a\n * capability present in the contract and absent from the authoring surface. Reads are not\n * offered the option: approval exists to gate EFFECTS, and gating a read teaches authors to\n * approve things reflexively, which is how an approval prompt stops being read.\n */\n requiresHumanApproval?: boolean;\n /** Route this write's approval to a reviewer (see {@link FunctionTool.humanApproval}). */\n humanApproval?: FunctionTool_HumanApprovalGate;\n },\n): FunctionTool {\n /** @wildo_source:part:end saas.backend.flows-actors.resource-write-tool */\n return {\n functionRef: options.functionRef ?? `resource.${resourceType}.${op}`,\n effect: FunctionToolEffect.WRITE,\n authority: { kind: FunctionToolAuthorityKind.PRINCIPAL_RESOURCE_OPERATION },\n requiresHumanApproval: options.requiresHumanApproval,\n humanApproval: options.humanApproval,\n // The arguments ARE the resource's fields (and `id` its row), so an exported correction reads their declarations (#1923).\n argumentsResource: { resourceType, ...(op === CoreResourceOperation.UPDATE ? { rowIdArgument: 'id' } : {}) },\n personalDataOutput: { kind: FunctionToolPersonalDataOutputKind.RECORDS_OF_RESOURCE, resourceType },\n description:\n options.description ??\n (op === CoreResourceOperation.CREATE\n ? `Create a new \"${resourceType}\" record on behalf of the current user from the provided fields. The record is owned by and scoped to the current user; ownership fields are set by the system, not from the arguments.`\n : `Update an existing \"${resourceType}\" record the current user owns. Pass the record \"id\" plus only the fields to change.`),\n inputSchema: options.inputSchema,\n execute: async (args: Record<string, unknown>, ctx: FunctionToolExecutionContext): Promise<unknown> => {\n const { servicesRegistryHandler, executionContextCreator } = ctx.services;\n const contextIds: Record<string, string> = ctx.organizationId ? { organizationId: ctx.organizationId } : {};\n\n // UPDATE addresses a row; CREATE does not. Split FIRST, before anything is resolved: this is\n // a check on the tool AUTHOR's own `inputSchema`, independent of the registry, and surfacing\n // it ahead of a resolution failure keeps the actionable message the actionable one.\n // `authorizeInController` then takes the addressed id and runs the row-scoped phases only\n // when there is one.\n const isUpdate = op === CoreResourceOperation.UPDATE;\n const { id } = args as { id?: string };\n if (isUpdate && (typeof id !== 'string' || id.length === 0)) {\n throw new Error(\n `resourceWriteTool(${resourceType}, update): the \"id\" argument is required — declare it in the tool's inputSchema.`,\n );\n }\n\n // The operation the tool ADVERTISES is the resource's public, URL-bearing default; dispatch\n // that exact one rather than re-resolving through the service layer's INTERNAL-preferred\n // resolver. See `resolveDispatchableOperation` for what diverged and what it cost.\n const operation = requireDispatchableOperation(ctx, OperationDispatchPlane.AGENT_TOOL, resourceType, op);\n // The idempotency key ARGUMENT (#747): on a variant that declares a key, the model's `idempotencyKey` argument is this\n // plane's `Idempotency-Key` header, taken out of the fields and routed to the service tier, whose request-outcome memory\n // answers the model's retry with the first result. The tool mints none: a key minted per execution would not survive the\n // model calling it again. A REQUIRED operation called without one is refused here, with the remedy, before authorizing,\n // charging or writing anything (#535 S5b-0); the tool's author advertises the argument in `inputSchema`.\n const taken = takeIdempotencyKeyToolArgument(operation, args, ({ code, field }) => new Error(\n `resourceWriteTool(${resourceType}, ${op}): ${code} — the \"${field}\" argument must be 1 to ${IDEMPOTENCY_KEY_MAX_LENGTH} printable ASCII characters.`,\n ));\n if (operation.idempotencyKey === ResourceOperationIdempotencyKeyRequirement.REQUIRED && taken.key === undefined) {\n throw new Error(\n `resourceWriteTool(${resourceType}, ${op}): the operation requires an idempotency key — pass the \"${IDEMPOTENCY_KEY_TOOL_ARGUMENT}\" `\n + 'argument, and declare it in the tool\\'s inputSchema so the model is told to send one.',\n );\n }\n const keyedOptions = taken.key !== undefined ? { idempotencyKey: taken.key } : undefined;\n const operationPath = ResourcesConfig_OperationPathUtils.extractOperationPath(operation) as ResourceConfiguration_OperationPath<any, any>;\n\n // Rebuild a scoped ExecutionContext from the CALLER's verified auth for this operation, then\n // apply the operation's own role + scope ACL against it (fail-closed) before anything is\n // written. The write runs as the user, never with an ACL bypass.\n if (!isUpdate) {\n // The seam authorizes as a COLLECTION call (no row addressed), charges the operation's own\n // budget after authorization so an unauthorized caller cannot spend an authorized one's, and\n // writes as the user — never with an ACL bypass.\n const created = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: op, contextIds, data: taken.args, options: keyedOptions });\n // Return the same JSON-safe, response-DTO-projected record the REST endpoint would, so no\n // `Date`/backend-only/secret reaches the model and the tool-loop CONTINUATION step validates.\n return toResponseSafeToolOutput(operation, created);\n }\n\n // UPDATE: the record \"id\" addresses the row AND is the authorization subject — the seam takes\n // one value for both, which is what makes authorizing a collection call while dispatching a\n // row call unrepresentable.\n const { id: _addressedRow, ...patch } = (taken.args ?? {}) as { id?: string };\n const updated = await dispatchResourceOperationAsTool({ ctx, resourceType, operationIdentifier: op, recordId: id, contextIds, data: patch, options: keyedOptions });\n return toResponseSafeToolOutput(operation, updated);\n },\n };\n}\n"]}