@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
@@ -12,7 +12,8 @@
12
12
  * 2026-11-09) — the claim set (`iss`, `scope`, `aud`, `exp`, `iat`) and "Key ID is optional, and is the ID of the service
13
13
  * account key used to sign the JWT". Fetched 2026-11-09 from https://www.rfc-editor.org.
14
14
  */
15
- import { ProviderServiceAccountKeyFormat, type ProviderServiceAccountTokenGrant } from '@wildo-ai/external-connectors-models';
15
+ import { ProviderServiceAccountKeyFormat, type ProviderRestRequestSigning, type ProviderServiceAccountTokenGrant } from '@wildo-ai/external-connectors-models';
16
+ import type { ProviderSdkSigningCredentials } from '@wildo-ai/external-connectors-private/backend';
16
17
  import { type MintedProviderClientCredentialsToken, ProviderClientCredentialsTokenCache, requestProviderAccessToken } from './provider-client-credentials-token.backend';
17
18
  /** What a service-account key yields: who the assertion is from, the key it is signed with, and that key's id. */
18
19
  export interface ProviderServiceAccountKey {
@@ -42,6 +43,13 @@ export declare function mintProviderServiceAccountToken(input: {
42
43
  * to remint and binds nothing another process would need.
43
44
  */
44
45
  export declare const PROVIDER_SERVICE_ACCOUNT_TOKENS: ProviderClientCredentialsTokenCache;
46
+ /**
47
+ * The signing credentials of a `requestSigning` AI arm (#3780), read from its DECLARED slots: the identity and the secret
48
+ * (both required), the session token when its slot is declared and set, and the Region (the deployment's
49
+ * `regionEnvVarName` when set, else the declared `region`, else none: a module whose SDK derives the Region from the
50
+ * resolved base URL needs neither). A required half unset refuses as NOT_CONFIGURED, naming the slot and never a value.
51
+ */
52
+ export declare function readProviderSdkSigningCredentials(providerRef: string, signing: ProviderRestRequestSigning, readSlot: (envVarName: string) => string | undefined): ProviderSdkSigningCredentials;
45
53
  /** The cache key: the provider, the token URL, the account and a hash of its key and scope. The key enters only hashed. */
46
54
  export declare function providerServiceAccountTokenKey(providerRef: string, grant: ProviderServiceAccountTokenGrant, key: ProviderServiceAccountKey): string;
47
55
  /**
@@ -50,10 +58,19 @@ export declare function providerServiceAccountTokenKey(providerRef: string, gran
50
58
  *
51
59
  * A parameter slot that is unset, or holds a value that could leave a path segment, refuses as NOT_CONFIGURED naming the
52
60
  * slot: the module would otherwise build a request path from it.
61
+ *
62
+ * An arm declaring `requestSigning` (#3780) authenticates with a signature its SDK computes: the credential is then the
63
+ * empty string, and the signing credentials are read from the arm's declared slots and returned beside it. An arm that
64
+ * declares both `apiKey` and `requestSigning`, or neither, refuses as NOT_CONFIGURED: which credential the call spends
65
+ * must never be a guess.
53
66
  */
54
67
  export declare function resolveProviderAiSdkCredential(input: {
55
68
  readonly providerRef: string;
56
69
  readonly arm: {
70
+ readonly apiKey?: {
71
+ readonly secretRef: string;
72
+ };
73
+ readonly requestSigning?: ProviderRestRequestSigning;
57
74
  readonly serviceAccountToken?: ProviderServiceAccountTokenGrant;
58
75
  readonly deploymentParameterEnvVarNames?: Readonly<Record<string, string>>;
59
76
  };
@@ -67,6 +84,7 @@ export declare function resolveProviderAiSdkCredential(input: {
67
84
  }): Promise<{
68
85
  readonly credential: string;
69
86
  readonly deploymentParameters?: Readonly<Record<string, string>>;
87
+ readonly requestSigningCredentials?: ProviderSdkSigningCredentials;
70
88
  }>;
71
89
  export {};
72
90
  //# sourceMappingURL=provider-service-account-token.backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider-service-account-token.backend.d.ts","sourceRoot":"","sources":["../../../../src/external-providers/services/provider-service-account-token.backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAGL,+BAA+B,EAC/B,KAAK,gCAAgC,EACtC,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACL,KAAK,oCAAoC,EACzC,mCAAmC,EAGnC,0BAA0B,EAC3B,MAAM,6CAA6C,CAAC;AAGrD,kHAAkH;AAClH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,+BAA+B,EAAE,GAAG,EAAE,MAAM,GAAG,yBAAyB,CAwBlJ;AAED,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AAE/E;;;GAGG;AACH,wBAAsB,+BAA+B,CAAC,KAAK,EAAE;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,gCAAgC,CAAC;IACjD,QAAQ,CAAC,GAAG,EAAE,yBAAyB,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,oCAAoC,CAAC,CAsChD;AAED;;;GAGG;AACH,eAAO,MAAM,+BAA+B,qCAA4C,CAAC;AAEzF,2HAA2H;AAC3H,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,gCAAgC,EAAE,GAAG,EAAE,yBAAyB,GAAG,MAAM,CAGnJ;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE;QACZ,QAAQ,CAAC,mBAAmB,CAAC,EAAE,gCAAgC,CAAC;QAChE,QAAQ,CAAC,8BAA8B,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAC5E,CAAC;IACF,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yFAAyF;IACzF,QAAQ,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC9D,QAAQ,CAAC,MAAM,CAAC,EAAE,mCAAmC,CAAC;IACtD,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC,CAiC7G"}
1
+ {"version":3,"file":"provider-service-account-token.backend.d.ts","sourceRoot":"","sources":["../../../../src/external-providers/services/provider-service-account-token.backend.ts"],"names":[],"mappings":"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"}
@@ -97,6 +97,34 @@ export async function mintProviderServiceAccountToken(input) {
97
97
  * to remint and binds nothing another process would need.
98
98
  */
99
99
  export const PROVIDER_SERVICE_ACCOUNT_TOKENS = new ProviderClientCredentialsTokenCache();
100
+ /**
101
+ * The signing credentials of a `requestSigning` AI arm (#3780), read from its DECLARED slots: the identity and the secret
102
+ * (both required), the session token when its slot is declared and set, and the Region (the deployment's
103
+ * `regionEnvVarName` when set, else the declared `region`, else none: a module whose SDK derives the Region from the
104
+ * resolved base URL needs neither). A required half unset refuses as NOT_CONFIGURED, naming the slot and never a value.
105
+ */
106
+ export function readProviderSdkSigningCredentials(providerRef, signing, readSlot) {
107
+ const required = (envVarName) => {
108
+ const value = readSlot(envVarName)?.trim();
109
+ if (value === undefined || value === '') {
110
+ throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}' signs its requests with '${envVarName}', which is not set.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);
111
+ }
112
+ return value;
113
+ };
114
+ const optional = (envVarName) => {
115
+ const value = envVarName === undefined ? undefined : readSlot(envVarName)?.trim();
116
+ return value === undefined || value === '' ? undefined : value;
117
+ };
118
+ const sessionToken = optional(signing.sessionTokenSecretRef);
119
+ const region = optional(signing.regionEnvVarName) ?? signing.region;
120
+ return {
121
+ scheme: signing.scheme,
122
+ keyId: required(signing.keyIdSecretRef),
123
+ secretKey: required(signing.secretKeySecretRef),
124
+ ...(sessionToken === undefined ? {} : { sessionToken }),
125
+ ...(region === undefined ? {} : { region }),
126
+ };
127
+ }
100
128
  /** The cache key: the provider, the token URL, the account and a hash of its key and scope. The key enters only hashed. */
101
129
  export function providerServiceAccountTokenKey(providerRef, grant, key) {
102
130
  const keyHash = createHash('sha256').update(key.privateKeyPem).update('\0').update(key.keyId ?? '').update('\0').update(grant.scope).digest('hex');
@@ -108,6 +136,11 @@ export function providerServiceAccountTokenKey(providerRef, grant, key) {
108
136
  *
109
137
  * A parameter slot that is unset, or holds a value that could leave a path segment, refuses as NOT_CONFIGURED naming the
110
138
  * slot: the module would otherwise build a request path from it.
139
+ *
140
+ * An arm declaring `requestSigning` (#3780) authenticates with a signature its SDK computes: the credential is then the
141
+ * empty string, and the signing credentials are read from the arm's declared slots and returned beside it. An arm that
142
+ * declares both `apiKey` and `requestSigning`, or neither, refuses as NOT_CONFIGURED: which credential the call spends
143
+ * must never be a guess.
111
144
  */
112
145
  export async function resolveProviderAiSdkCredential(input) {
113
146
  const { providerRef, arm } = input;
@@ -125,9 +158,16 @@ export async function resolveProviderAiSdkCredential(input) {
125
158
  }
126
159
  (deploymentParameters ??= {})[name] = value;
127
160
  }
161
+ const parameters = deploymentParameters === undefined ? {} : { deploymentParameters };
162
+ if ((arm.apiKey === undefined) === (arm.requestSigning === undefined)) {
163
+ throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}' declares both or neither of \`apiKey\` and \`requestSigning\` on an AI arm, so which credential a call spends is unknown.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);
164
+ }
165
+ if (arm.requestSigning !== undefined) {
166
+ return { credential: '', ...parameters, requestSigningCredentials: readProviderSdkSigningCredentials(providerRef, arm.requestSigning, input.readSlot) };
167
+ }
128
168
  const grant = arm.serviceAccountToken;
129
169
  if (grant === undefined)
130
- return { credential: input.secretValue, ...(deploymentParameters === undefined ? {} : { deploymentParameters }) };
170
+ return { credential: input.secretValue, ...parameters };
131
171
  const key = readProviderServiceAccountKey(providerRef, grant.keyFormat, input.secretValue);
132
172
  const credential = await (input.tokens ?? PROVIDER_SERVICE_ACCOUNT_TOKENS).getOrMint(providerServiceAccountTokenKey(providerRef, grant, key), () => mintProviderServiceAccountToken({
133
173
  providerRef,
@@ -1 +1 @@
1
- {"version":3,"file":"provider-service-account-token.backend.js","sourceRoot":"","sources":["../../../../src/external-providers/services/provider-service-account-token.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The bearer token of an AI arm that authenticates with a SERVICE ACCOUNT (#3425): the key in the arm's `apiKey` slot is\n * exchanged at the contract's token endpoint through the JWT-bearer grant (RFC 7523 §2.1), the token is cached until a\n * minute before it expires, and the TOKEN, never the key, reaches the arm's `sdkFactory`.\n *\n * It shares the connector lane's token pieces with the client-credentials grant: the one request-and-answer reader\n * (`requestProviderAccessToken`), the per-process cache and the assertion signer (#3402).\n *\n * spec-cite: RFC 7523 §2.1 — \"The value of the \"grant_type\" is \"urn:ietf:params:oauth:grant-type:jwt-bearer\".\"; RFC 7521\n * §4.1 — `assertion`: \"REQUIRED. The assertion being used as an authorization grant.\"; Google Identity, \"Using OAuth 2.0\n * for Server to Server Applications\" (https://developers.google.com/identity/protocols/oauth2/service-account, fetched\n * 2026-11-09) — the claim set (`iss`, `scope`, `aud`, `exp`, `iat`) and \"Key ID is optional, and is the ID of the service\n * account key used to sign the JWT\". Fetched 2026-11-09 from https://www.rfc-editor.org.\n */\n\nimport { ProviderCallAccount } from '@wildo-ai/saas-models';\nimport { admitProviderCallUnderDataResidency } from '~wildo-backend-lib/external-providers/data-residency/provider-call-data-residency-gate.backend';\nimport { createHash } from 'node:crypto';\n\nimport {\n PROVIDER_CLIENT_ASSERTION_DEFAULT_LIFETIME_SECONDS,\n PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE,\n ProviderServiceAccountKeyFormat,\n type ProviderServiceAccountTokenGrant,\n} from '@wildo-ai/external-connectors-models';\n\nimport {\n type MintedProviderClientCredentialsToken,\n ProviderClientCredentialsTokenCache,\n ProviderClientCredentialsTokenError,\n ProviderClientCredentialsTokenFailure,\n requestProviderAccessToken,\n} from './provider-client-credentials-token.backend';\nimport { PROVIDER_JWT_BEARER_GRANT_TYPE, ProviderJwtAssertionError, signProviderJwtAssertion } from './provider-jwt-assertion.backend';\n\n/** What a service-account key yields: who the assertion is from, the key it is signed with, and that key's id. */\nexport interface ProviderServiceAccountKey {\n readonly issuer: string;\n readonly privateKeyPem: string;\n readonly keyId?: string;\n}\n\n/**\n * Reads the key in the declared format, or refuses as NOT_CONFIGURED naming the field that is missing. Never quotes the\n * value: it holds a private key.\n */\nexport function readProviderServiceAccountKey(providerRef: string, format: ProviderServiceAccountKeyFormat, raw: string): ProviderServiceAccountKey {\n const refuse = (why: string): never => {\n throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}': the service-account key ${why}.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n };\n switch (format) {\n case ProviderServiceAccountKeyFormat.GOOGLE_SERVICE_ACCOUNT_JSON: {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return refuse('is not a JSON service-account key file');\n }\n const key = parsed !== null && typeof parsed === 'object' ? parsed as Record<string, unknown> : {};\n if (typeof key.client_email !== 'string' || key.client_email === '') return refuse('has no client_email');\n if (typeof key.private_key !== 'string' || key.private_key === '') return refuse('has no private_key');\n return {\n issuer: key.client_email,\n privateKeyPem: key.private_key,\n ...(typeof key.private_key_id === 'string' && key.private_key_id !== '' ? { keyId: key.private_key_id } : {}),\n };\n }\n default:\n return refuse(`is in a format this engine does not read (${String(format)})`);\n }\n}\n\ntype FetchLike = Parameters<typeof requestProviderAccessToken>[0]['fetchImpl'];\n\n/**\n * Mints one token: signs the assertion (`iss` the account, `scope`, `aud` the token URL, `iat`, `exp`), refuses a token\n * URL whose host the grant does not admit before anything is signed, and posts the JWT-bearer grant.\n */\nexport async function mintProviderServiceAccountToken(input: {\n readonly providerRef: string;\n readonly grant: ProviderServiceAccountTokenGrant;\n readonly key: ProviderServiceAccountKey;\n readonly fetchImpl?: FetchLike;\n readonly now?: () => number;\n}): Promise<MintedProviderClientCredentialsToken> {\n const { providerRef, grant, key } = input;\n const now = input.now ?? Date.now;\n const host = /^https:\\/\\/([^/:?#]+)(?::\\d+)?\\//.exec(grant.tokenUrl)?.[1]?.toLowerCase();\n if (host === undefined || !grant.tokenHosts.some((tokenHost) => tokenHost.toLowerCase() === host)) {\n throw new ProviderClientCredentialsTokenError(\n `Provider '${providerRef}' declares a service-account token URL on a host its tokenHosts do not admit, so no assertion is sent.`,\n ProviderClientCredentialsTokenFailure.NOT_CONFIGURED,\n );\n }\n const issuedAtSeconds = Math.floor(now() / 1000);\n let assertion: string;\n try {\n assertion = await signProviderJwtAssertion({\n providerRef,\n privateKeyPem: key.privateKeyPem,\n algorithm: grant.algorithm,\n ...(key.keyId === undefined ? {} : { keyId: key.keyId }),\n claims: {\n iss: key.issuer,\n scope: grant.scope,\n aud: grant.tokenUrl,\n iat: issuedAtSeconds,\n exp: issuedAtSeconds + (grant.assertionLifetimeSeconds ?? PROVIDER_CLIENT_ASSERTION_DEFAULT_LIFETIME_SECONDS),\n },\n });\n } catch (error) {\n if (error instanceof ProviderJwtAssertionError) throw new ProviderClientCredentialsTokenError(error.message, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n throw error;\n }\n return requestProviderAccessToken({\n providerRef,\n url: grant.tokenUrl,\n headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },\n body: new URLSearchParams({ grant_type: PROVIDER_JWT_BEARER_GRANT_TYPE, assertion }).toString(),\n ...(input.fetchImpl === undefined ? {} : { fetchImpl: input.fetchImpl }),\n now,\n });\n}\n\n/**\n * The process's service-account tokens. In-process for the client-credentials cache's reason: a token costs one request\n * to remint and binds nothing another process would need.\n */\nexport const PROVIDER_SERVICE_ACCOUNT_TOKENS = new ProviderClientCredentialsTokenCache();\n\n/** The cache key: the provider, the token URL, the account and a hash of its key and scope. The key enters only hashed. */\nexport function providerServiceAccountTokenKey(providerRef: string, grant: ProviderServiceAccountTokenGrant, key: ProviderServiceAccountKey): string {\n const keyHash = createHash('sha256').update(key.privateKeyPem).update('\\0').update(key.keyId ?? '').update('\\0').update(grant.scope).digest('hex');\n return JSON.stringify([providerRef, grant.tokenUrl, key.issuer, keyHash]);\n}\n\n/**\n * What an AI arm's `sdkFactory` is called with (#3425): the credential (the slot's value, or the bearer token minted from\n * the service-account key in it) and the deployment parameters read from their declared slots.\n *\n * A parameter slot that is unset, or holds a value that could leave a path segment, refuses as NOT_CONFIGURED naming the\n * slot: the module would otherwise build a request path from it.\n */\nexport async function resolveProviderAiSdkCredential(input: {\n readonly providerRef: string;\n readonly arm: {\n readonly serviceAccountToken?: ProviderServiceAccountTokenGrant;\n readonly deploymentParameterEnvVarNames?: Readonly<Record<string, string>>;\n };\n /** The value of the arm's `apiKey` slot. */\n readonly secretValue: string;\n /** Reads a DECLARED slot of the provider by env-var name (the registry's own reader). */\n readonly readSlot: (envVarName: string) => string | undefined;\n readonly tokens?: ProviderClientCredentialsTokenCache;\n readonly fetchImpl?: FetchLike;\n readonly now?: () => number;\n}): Promise<{ readonly credential: string; readonly deploymentParameters?: Readonly<Record<string, string>> }> {\n const { providerRef, arm } = input;\n // #2294: every model, image and embeddings call passes this door with the application's credential, right before its\n // client is built, so an organization's data residency is applied here once for all three.\n await admitProviderCallUnderDataResidency({ providerRef, account: ProviderCallAccount.APPLICATION });\n let deploymentParameters: Record<string, string> | undefined;\n for (const [name, envVarName] of Object.entries(arm.deploymentParameterEnvVarNames ?? {})) {\n const value = input.readSlot(envVarName)?.trim();\n if (value === undefined || value === '') {\n throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}' names its ${name} in '${envVarName}', which is not set.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n }\n if (!PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE.test(value)) {\n throw new ProviderClientCredentialsTokenError(\n `Provider '${providerRef}': '${envVarName}' is not an identifier (letters, digits, '.', '_', '-'), so it cannot name the ${name}.`,\n ProviderClientCredentialsTokenFailure.NOT_CONFIGURED,\n );\n }\n (deploymentParameters ??= {})[name] = value;\n }\n const grant = arm.serviceAccountToken;\n if (grant === undefined) return { credential: input.secretValue, ...(deploymentParameters === undefined ? {} : { deploymentParameters }) };\n const key = readProviderServiceAccountKey(providerRef, grant.keyFormat, input.secretValue);\n const credential = await (input.tokens ?? PROVIDER_SERVICE_ACCOUNT_TOKENS).getOrMint(\n providerServiceAccountTokenKey(providerRef, grant, key),\n () => mintProviderServiceAccountToken({\n providerRef,\n grant,\n key,\n ...(input.fetchImpl === undefined ? {} : { fetchImpl: input.fetchImpl }),\n ...(input.now === undefined ? {} : { now: input.now }),\n }),\n );\n return { credential, ...(deploymentParameters === undefined ? {} : { deploymentParameters }) };\n}\n"]}
1
+ {"version":3,"file":"provider-service-account-token.backend.js","sourceRoot":"","sources":["../../../../src/external-providers/services/provider-service-account-token.backend.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The bearer token of an AI arm that authenticates with a SERVICE ACCOUNT (#3425): the key in the arm's `apiKey` slot is\n * exchanged at the contract's token endpoint through the JWT-bearer grant (RFC 7523 §2.1), the token is cached until a\n * minute before it expires, and the TOKEN, never the key, reaches the arm's `sdkFactory`.\n *\n * It shares the connector lane's token pieces with the client-credentials grant: the one request-and-answer reader\n * (`requestProviderAccessToken`), the per-process cache and the assertion signer (#3402).\n *\n * spec-cite: RFC 7523 §2.1 — \"The value of the \"grant_type\" is \"urn:ietf:params:oauth:grant-type:jwt-bearer\".\"; RFC 7521\n * §4.1 — `assertion`: \"REQUIRED. The assertion being used as an authorization grant.\"; Google Identity, \"Using OAuth 2.0\n * for Server to Server Applications\" (https://developers.google.com/identity/protocols/oauth2/service-account, fetched\n * 2026-11-09) — the claim set (`iss`, `scope`, `aud`, `exp`, `iat`) and \"Key ID is optional, and is the ID of the service\n * account key used to sign the JWT\". Fetched 2026-11-09 from https://www.rfc-editor.org.\n */\n\nimport { ProviderCallAccount } from '@wildo-ai/saas-models';\nimport { admitProviderCallUnderDataResidency } from '~wildo-backend-lib/external-providers/data-residency/provider-call-data-residency-gate.backend';\nimport { createHash } from 'node:crypto';\n\nimport {\n PROVIDER_CLIENT_ASSERTION_DEFAULT_LIFETIME_SECONDS,\n PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE,\n ProviderServiceAccountKeyFormat,\n type ProviderRestRequestSigning,\n type ProviderServiceAccountTokenGrant,\n} from '@wildo-ai/external-connectors-models';\nimport type { ProviderSdkSigningCredentials } from '@wildo-ai/external-connectors-private/backend';\n\nimport {\n type MintedProviderClientCredentialsToken,\n ProviderClientCredentialsTokenCache,\n ProviderClientCredentialsTokenError,\n ProviderClientCredentialsTokenFailure,\n requestProviderAccessToken,\n} from './provider-client-credentials-token.backend';\nimport { PROVIDER_JWT_BEARER_GRANT_TYPE, ProviderJwtAssertionError, signProviderJwtAssertion } from './provider-jwt-assertion.backend';\n\n/** What a service-account key yields: who the assertion is from, the key it is signed with, and that key's id. */\nexport interface ProviderServiceAccountKey {\n readonly issuer: string;\n readonly privateKeyPem: string;\n readonly keyId?: string;\n}\n\n/**\n * Reads the key in the declared format, or refuses as NOT_CONFIGURED naming the field that is missing. Never quotes the\n * value: it holds a private key.\n */\nexport function readProviderServiceAccountKey(providerRef: string, format: ProviderServiceAccountKeyFormat, raw: string): ProviderServiceAccountKey {\n const refuse = (why: string): never => {\n throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}': the service-account key ${why}.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n };\n switch (format) {\n case ProviderServiceAccountKeyFormat.GOOGLE_SERVICE_ACCOUNT_JSON: {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return refuse('is not a JSON service-account key file');\n }\n const key = parsed !== null && typeof parsed === 'object' ? parsed as Record<string, unknown> : {};\n if (typeof key.client_email !== 'string' || key.client_email === '') return refuse('has no client_email');\n if (typeof key.private_key !== 'string' || key.private_key === '') return refuse('has no private_key');\n return {\n issuer: key.client_email,\n privateKeyPem: key.private_key,\n ...(typeof key.private_key_id === 'string' && key.private_key_id !== '' ? { keyId: key.private_key_id } : {}),\n };\n }\n default:\n return refuse(`is in a format this engine does not read (${String(format)})`);\n }\n}\n\ntype FetchLike = Parameters<typeof requestProviderAccessToken>[0]['fetchImpl'];\n\n/**\n * Mints one token: signs the assertion (`iss` the account, `scope`, `aud` the token URL, `iat`, `exp`), refuses a token\n * URL whose host the grant does not admit before anything is signed, and posts the JWT-bearer grant.\n */\nexport async function mintProviderServiceAccountToken(input: {\n readonly providerRef: string;\n readonly grant: ProviderServiceAccountTokenGrant;\n readonly key: ProviderServiceAccountKey;\n readonly fetchImpl?: FetchLike;\n readonly now?: () => number;\n}): Promise<MintedProviderClientCredentialsToken> {\n const { providerRef, grant, key } = input;\n const now = input.now ?? Date.now;\n const host = /^https:\\/\\/([^/:?#]+)(?::\\d+)?\\//.exec(grant.tokenUrl)?.[1]?.toLowerCase();\n if (host === undefined || !grant.tokenHosts.some((tokenHost) => tokenHost.toLowerCase() === host)) {\n throw new ProviderClientCredentialsTokenError(\n `Provider '${providerRef}' declares a service-account token URL on a host its tokenHosts do not admit, so no assertion is sent.`,\n ProviderClientCredentialsTokenFailure.NOT_CONFIGURED,\n );\n }\n const issuedAtSeconds = Math.floor(now() / 1000);\n let assertion: string;\n try {\n assertion = await signProviderJwtAssertion({\n providerRef,\n privateKeyPem: key.privateKeyPem,\n algorithm: grant.algorithm,\n ...(key.keyId === undefined ? {} : { keyId: key.keyId }),\n claims: {\n iss: key.issuer,\n scope: grant.scope,\n aud: grant.tokenUrl,\n iat: issuedAtSeconds,\n exp: issuedAtSeconds + (grant.assertionLifetimeSeconds ?? PROVIDER_CLIENT_ASSERTION_DEFAULT_LIFETIME_SECONDS),\n },\n });\n } catch (error) {\n if (error instanceof ProviderJwtAssertionError) throw new ProviderClientCredentialsTokenError(error.message, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n throw error;\n }\n return requestProviderAccessToken({\n providerRef,\n url: grant.tokenUrl,\n headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json' },\n body: new URLSearchParams({ grant_type: PROVIDER_JWT_BEARER_GRANT_TYPE, assertion }).toString(),\n ...(input.fetchImpl === undefined ? {} : { fetchImpl: input.fetchImpl }),\n now,\n });\n}\n\n/**\n * The process's service-account tokens. In-process for the client-credentials cache's reason: a token costs one request\n * to remint and binds nothing another process would need.\n */\nexport const PROVIDER_SERVICE_ACCOUNT_TOKENS = new ProviderClientCredentialsTokenCache();\n\n/**\n * The signing credentials of a `requestSigning` AI arm (#3780), read from its DECLARED slots: the identity and the secret\n * (both required), the session token when its slot is declared and set, and the Region (the deployment's\n * `regionEnvVarName` when set, else the declared `region`, else none: a module whose SDK derives the Region from the\n * resolved base URL needs neither). A required half unset refuses as NOT_CONFIGURED, naming the slot and never a value.\n */\nexport function readProviderSdkSigningCredentials(\n providerRef: string,\n signing: ProviderRestRequestSigning,\n readSlot: (envVarName: string) => string | undefined,\n): ProviderSdkSigningCredentials {\n const required = (envVarName: string): string => {\n const value = readSlot(envVarName)?.trim();\n if (value === undefined || value === '') {\n throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}' signs its requests with '${envVarName}', which is not set.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n }\n return value;\n };\n const optional = (envVarName: string | undefined): string | undefined => {\n const value = envVarName === undefined ? undefined : readSlot(envVarName)?.trim();\n return value === undefined || value === '' ? undefined : value;\n };\n const sessionToken = optional(signing.sessionTokenSecretRef);\n const region = optional(signing.regionEnvVarName) ?? signing.region;\n return {\n scheme: signing.scheme,\n keyId: required(signing.keyIdSecretRef),\n secretKey: required(signing.secretKeySecretRef),\n ...(sessionToken === undefined ? {} : { sessionToken }),\n ...(region === undefined ? {} : { region }),\n };\n}\n\n/** The cache key: the provider, the token URL, the account and a hash of its key and scope. The key enters only hashed. */\nexport function providerServiceAccountTokenKey(providerRef: string, grant: ProviderServiceAccountTokenGrant, key: ProviderServiceAccountKey): string {\n const keyHash = createHash('sha256').update(key.privateKeyPem).update('\\0').update(key.keyId ?? '').update('\\0').update(grant.scope).digest('hex');\n return JSON.stringify([providerRef, grant.tokenUrl, key.issuer, keyHash]);\n}\n\n/**\n * What an AI arm's `sdkFactory` is called with (#3425): the credential (the slot's value, or the bearer token minted from\n * the service-account key in it) and the deployment parameters read from their declared slots.\n *\n * A parameter slot that is unset, or holds a value that could leave a path segment, refuses as NOT_CONFIGURED naming the\n * slot: the module would otherwise build a request path from it.\n *\n * An arm declaring `requestSigning` (#3780) authenticates with a signature its SDK computes: the credential is then the\n * empty string, and the signing credentials are read from the arm's declared slots and returned beside it. An arm that\n * declares both `apiKey` and `requestSigning`, or neither, refuses as NOT_CONFIGURED: which credential the call spends\n * must never be a guess.\n */\nexport async function resolveProviderAiSdkCredential(input: {\n readonly providerRef: string;\n readonly arm: {\n readonly apiKey?: { readonly secretRef: string };\n readonly requestSigning?: ProviderRestRequestSigning;\n readonly serviceAccountToken?: ProviderServiceAccountTokenGrant;\n readonly deploymentParameterEnvVarNames?: Readonly<Record<string, string>>;\n };\n /** The value of the arm's `apiKey` slot. */\n readonly secretValue: string;\n /** Reads a DECLARED slot of the provider by env-var name (the registry's own reader). */\n readonly readSlot: (envVarName: string) => string | undefined;\n readonly tokens?: ProviderClientCredentialsTokenCache;\n readonly fetchImpl?: FetchLike;\n readonly now?: () => number;\n}): Promise<{\n readonly credential: string;\n readonly deploymentParameters?: Readonly<Record<string, string>>;\n readonly requestSigningCredentials?: ProviderSdkSigningCredentials;\n}> {\n const { providerRef, arm } = input;\n // #2294: every model, image and embeddings call passes this door with the application's credential, right before its\n // client is built, so an organization's data residency is applied here once for all three.\n await admitProviderCallUnderDataResidency({ providerRef, account: ProviderCallAccount.APPLICATION });\n let deploymentParameters: Record<string, string> | undefined;\n for (const [name, envVarName] of Object.entries(arm.deploymentParameterEnvVarNames ?? {})) {\n const value = input.readSlot(envVarName)?.trim();\n if (value === undefined || value === '') {\n throw new ProviderClientCredentialsTokenError(`Provider '${providerRef}' names its ${name} in '${envVarName}', which is not set.`, ProviderClientCredentialsTokenFailure.NOT_CONFIGURED);\n }\n if (!PROVIDER_DEPLOYMENT_PARAMETER_VALUE_SHAPE.test(value)) {\n throw new ProviderClientCredentialsTokenError(\n `Provider '${providerRef}': '${envVarName}' is not an identifier (letters, digits, '.', '_', '-'), so it cannot name the ${name}.`,\n ProviderClientCredentialsTokenFailure.NOT_CONFIGURED,\n );\n }\n (deploymentParameters ??= {})[name] = value;\n }\n const parameters = deploymentParameters === undefined ? {} : { deploymentParameters };\n if ((arm.apiKey === undefined) === (arm.requestSigning === undefined)) {\n throw new ProviderClientCredentialsTokenError(\n `Provider '${providerRef}' declares both or neither of \\`apiKey\\` and \\`requestSigning\\` on an AI arm, so which credential a call spends is unknown.`,\n ProviderClientCredentialsTokenFailure.NOT_CONFIGURED,\n );\n }\n if (arm.requestSigning !== undefined) {\n return { credential: '', ...parameters, requestSigningCredentials: readProviderSdkSigningCredentials(providerRef, arm.requestSigning, input.readSlot) };\n }\n const grant = arm.serviceAccountToken;\n if (grant === undefined) return { credential: input.secretValue, ...parameters };\n const key = readProviderServiceAccountKey(providerRef, grant.keyFormat, input.secretValue);\n const credential = await (input.tokens ?? PROVIDER_SERVICE_ACCOUNT_TOKENS).getOrMint(\n providerServiceAccountTokenKey(providerRef, grant, key),\n () => mintProviderServiceAccountToken({\n providerRef,\n grant,\n key,\n ...(input.fetchImpl === undefined ? {} : { fetchImpl: input.fetchImpl }),\n ...(input.now === undefined ? {} : { now: input.now }),\n }),\n );\n return { credential, ...(deploymentParameters === undefined ? {} : { deploymentParameters }) };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { Request } from 'express';
2
- import { type AnyResourceConfiguration, type ResourceConfiguration_Operation, type ResourceConfiguration_Operation_UrlInitiatorInfo } from '@wildo-ai/saas-models';
2
+ import { ResourcePrimaryScope, type AnyResourceConfiguration, type ResourceConfiguration_Operation, type ResourceConfiguration_Operation_UrlInitiatorInfo } from '@wildo-ai/saas-models';
3
3
  import type { ResourcesRegistryBackendService } from '../../resources/services/resources-registry.backend.service';
4
4
  import type { RepositoriesRegistryHandlerBackendService } from '../../base-classes/services/repositories/repositories-registry-handler.backend.service';
5
5
  import type { ExecutionContextCreatorBackendService } from '../../runtime/services/execution-context-creator.backend.service';
@@ -16,6 +16,20 @@ export interface FileParentReadDependencies {
16
16
  errorBuilder: ErrorBuilderBackendService;
17
17
  fileFieldDetection: FileFieldDetectionBackendService;
18
18
  }
19
+ /**
20
+ * The record a caller is asked to be able to READ, and the scope it lives in: what both a file's parent (#file shares)
21
+ * and an approval seal's subject (#2913) are authorized through. The scope ids come from where the record was found,
22
+ * never from the caller: they only shape the routes the record's READ is tried through, and each route is then
23
+ * authorized with the caller's own credentials.
24
+ */
25
+ export interface RecordReadBinding {
26
+ readonly resourceType: string;
27
+ readonly resourceId: string;
28
+ readonly primaryScope: ResourcePrimaryScope;
29
+ readonly applicationId: string;
30
+ readonly organizationId?: string | null;
31
+ readonly userId?: string | null;
32
+ }
19
33
  export interface FileParentReadCandidate {
20
34
  initiatorInfo: ResourceConfiguration_Operation_UrlInitiatorInfo;
21
35
  params: Record<string, string>;
@@ -25,7 +39,7 @@ export interface FileParentReadCandidate {
25
39
  * from the target row's compiled FK, never caller-supplied guesses or a fabricated shorter route.
26
40
  * Arrays enumerate genuine alternatives lazily: a caller can be allowed through its second parent.
27
41
  */
28
- export declare function fileParentReadCandidates(configuration: AnyResourceConfiguration, operation: ResourceConfiguration_Operation<any, any, any>, fieldIdentifiers: Record<string, string>, binding: FileShareBinding, parent: Record<string, unknown>): Generator<FileParentReadCandidate>;
42
+ export declare function fileParentReadCandidates(configuration: AnyResourceConfiguration, operation: ResourceConfiguration_Operation<any, any, any>, fieldIdentifiers: Record<string, string>, binding: RecordReadBinding, parent: Record<string, unknown>): Generator<FileParentReadCandidate>;
29
43
  /**
30
44
  * Resolve routing evidence privately, then re-enter the real request authentication boundary.
31
45
  * The infrastructure lookup is NOT authority: only a fresh parent READ context plus addressed
@@ -33,4 +47,15 @@ export declare function fileParentReadCandidates(configuration: AnyResourceConfi
33
47
  * context here: that misses operation-specific delegated credentials and token policies.
34
48
  */
35
49
  export declare function authorizeFileParentRead(request: Request, binding: FileShareBinding, dependencies: FileParentReadDependencies): Promise<ExecutionContext<any>>;
50
+ /**
51
+ * Admit a caller to something that belongs to ONE record — a file in its field, an approval seal it stores (#2913) —
52
+ * exactly when the record's own READ operation admits them, with their own credentials, and the record (as read in that
53
+ * caller's scope) still `holds` the thing. Every refusal is `notFound()`, so a caller learns nothing about a record they
54
+ * may not read.
55
+ *
56
+ * The routing is derived only from routes the READ operation declares, filled from the record's own scope and foreign
57
+ * keys (`fileParentReadCandidates`); the infrastructure read that finds them is NOT authority. Answers the execution
58
+ * context the admitted route built.
59
+ */
60
+ export declare function authorizeRecordReadAsCaller(request: Request, binding: RecordReadBinding, holds: (row: Record<string, unknown>) => boolean, dependencies: Pick<FileParentReadDependencies, 'resourcesRegistry' | 'repositoriesRegistry' | 'executionContextCreator' | 'authorizationsService'>, notFound: () => unknown): Promise<ExecutionContext<any>>;
36
61
  //# sourceMappingURL=file-parent-read-context.backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-parent-read-context.backend.d.ts","sourceRoot":"","sources":["../../../../src/files/utils/file-parent-read-context.backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAIL,KAAK,wBAAwB,EAAE,KAAK,+BAA+B,EAAE,KAAK,gDAAgD,EAC3H,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,0EAA0E,CAAC;AAChI,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,qGAAqG,CAAC;AACrK,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,+EAA+E,CAAC;AAC3I,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oFAAoF,CAAC;AACvI,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kEAAkE,CAAC;AACnH,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,kDAAkD,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qEAAqE,CAAC;AAC5G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,+BAA+B,CAAC;IACnD,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,uBAAuB,EAAE,qCAAqC,CAAC;IAC/D,qBAAqB,EAAE,4BAA4B,CAAC;IACpD,YAAY,EAAE,0BAA0B,CAAC;IACzC,kBAAkB,EAAE,gCAAgC,CAAC;CACtD;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,gDAAgD,CAAC;IAChE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAWD;;;;GAIG;AACH,wBAAiB,wBAAwB,CACvC,aAAa,EAAE,wBAAwB,EACvC,SAAS,EAAE,+BAA+B,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACzD,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,SAAS,CAAC,uBAAuB,CAAC,CAkCpC;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,0BAA0B,GACvC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CA4ChC"}
1
+ {"version":3,"file":"file-parent-read-context.backend.d.ts","sourceRoot":"","sources":["../../../../src/files/utils/file-parent-read-context.backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACwF,oBAAoB,EAGjH,KAAK,wBAAwB,EAAE,KAAK,+BAA+B,EAAE,KAAK,gDAAgD,EAC3H,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,0EAA0E,CAAC;AAChI,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,qGAAqG,CAAC;AACrK,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,+EAA+E,CAAC;AAC3I,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oFAAoF,CAAC;AACvI,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kEAAkE,CAAC;AACnH,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,kDAAkD,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qEAAqE,CAAC;AAC5G,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,MAAM,WAAW,0BAA0B;IACzC,iBAAiB,EAAE,+BAA+B,CAAC;IACnD,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,uBAAuB,EAAE,qCAAqC,CAAC;IAC/D,qBAAqB,EAAE,4BAA4B,CAAC;IACpD,YAAY,EAAE,0BAA0B,CAAC;IACzC,kBAAkB,EAAE,gCAAgC,CAAC;CACtD;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,oBAAoB,CAAC;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,gDAAgD,CAAC;IAChE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAWD;;;;GAIG;AACH,wBAAiB,wBAAwB,CACvC,aAAa,EAAE,wBAAwB,EACvC,SAAS,EAAE,+BAA+B,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACzD,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,SAAS,CAAC,uBAAuB,CAAC,CAkCpC;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,gBAAgB,EACzB,YAAY,EAAE,0BAA0B,GACvC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAQhC;AAED;;;;;;;;;GASG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,EAChD,YAAY,EAAE,IAAI,CAAC,0BAA0B,EAAE,mBAAmB,GAAG,sBAAsB,GAAG,yBAAyB,GAAG,uBAAuB,CAAC,EAClJ,QAAQ,EAAE,MAAM,OAAO,GACtB,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CA0ChC"}
@@ -67,26 +67,45 @@ export function* fileParentReadCandidates(configuration, operation, fieldIdentif
67
67
  * context here: that misses operation-specific delegated credentials and token policies.
68
68
  */
69
69
  export async function authorizeFileParentRead(request, binding, dependencies) {
70
- const { resourcesRegistry, repositoriesRegistry, executionContextCreator, authorizationsService, errorBuilder, fileFieldDetection } = dependencies;
70
+ const { resourcesRegistry, errorBuilder, fileFieldDetection } = dependencies;
71
71
  const notFound = () => errorBuilder.buildError(ErrorType.NOT_FOUND, undefined, {
72
72
  customMessageReference: ErrorCustomMessageReference.FILE_NOT_FOUND, context: { fileId: binding.fileId },
73
73
  });
74
+ if (resourcesRegistry.getResourceConfiguration(binding.resourceType).resourcePrimaryScope !== binding.primaryScope
75
+ || !fileFieldDetection.getFileFieldMetadata(binding.resourceType, binding.fieldName))
76
+ throw notFound();
77
+ return authorizeRecordReadAsCaller(request, binding, (row) => fileFieldContainsFileId(row, binding.fieldName, binding.fileId), dependencies, notFound);
78
+ }
79
+ /**
80
+ * Admit a caller to something that belongs to ONE record — a file in its field, an approval seal it stores (#2913) —
81
+ * exactly when the record's own READ operation admits them, with their own credentials, and the record (as read in that
82
+ * caller's scope) still `holds` the thing. Every refusal is `notFound()`, so a caller learns nothing about a record they
83
+ * may not read.
84
+ *
85
+ * The routing is derived only from routes the READ operation declares, filled from the record's own scope and foreign
86
+ * keys (`fileParentReadCandidates`); the infrastructure read that finds them is NOT authority. Answers the execution
87
+ * context the admitted route built.
88
+ */
89
+ export async function authorizeRecordReadAsCaller(request, binding, holds, dependencies, notFound) {
90
+ const { resourcesRegistry, repositoriesRegistry, executionContextCreator, authorizationsService } = dependencies;
74
91
  const resourceType = binding.resourceType;
75
92
  const configuration = resourcesRegistry.getResourceConfiguration(resourceType);
76
- if (configuration.resourcePrimaryScope !== binding.primaryScope || !fileFieldDetection.getFileFieldMetadata(resourceType, binding.fieldName)
93
+ if (!configuration || configuration.resourcePrimaryScope !== binding.primaryScope
77
94
  || !resourcesRegistry.hasOperationPathDefault(resourceType, CoreResourceOperation.READ))
78
95
  throw notFound();
79
96
  const operation = resourcesRegistry.getOperationFromPath(resourcesRegistry.getOperationPathDefault(resourceType, CoreResourceOperation.READ));
80
97
  const scopeField = PRIMARY_SCOPE_TO_FIELD_IDENTIFIER[binding.primaryScope];
81
98
  const scopeId = binding.primaryScope === ResourcePrimaryScope.APPLICATION ? binding.applicationId
82
99
  : binding.primaryScope === ResourcePrimaryScope.ORGANIZATIONS ? binding.organizationId : binding.userId;
100
+ if (!scopeId)
101
+ throw notFound();
83
102
  const scopePath = configuration.resourceFieldIdentifier === scopeField ? '_id' : scopeField;
84
103
  if (scopePath === '_id' && binding.resourceId !== scopeId)
85
104
  throw notFound();
86
105
  // No caller-visible fields escape this exact key+scope, retention-hidden bootstrap. In particular
87
106
  // it does not borrow a fabricated unit-narrowing stamp before target authorization can establish one.
88
107
  const parent = await repositoriesRegistry.readUnscopedByKey(resourceType, { _id: binding.resourceId, [scopePath]: scopeId });
89
- if (!parent || !fileFieldContainsFileId(parent, binding.fieldName, binding.fileId))
108
+ if (!parent || !holds(parent))
90
109
  throw notFound();
91
110
  const fields = resourcesRegistry.getAllResourceFieldIdentifiers();
92
111
  for (const candidate of fileParentReadCandidates(configuration, operation, fields, binding, parent)) {
@@ -100,7 +119,7 @@ export async function authorizeFileParentRead(request, binding, dependencies) {
100
119
  await authorizationsService.authorizeInController(binding.resourceId, context);
101
120
  const current = await repositoriesRegistry.getRepositoryOrThrow(resourceType, context)
102
121
  .readForInternalScan(context, { _id: binding.resourceId });
103
- if (!current || !fileFieldContainsFileId(current, binding.fieldName, binding.fileId))
122
+ if (!current || !holds(current))
104
123
  continue;
105
124
  // Parent FK changes between bootstrap and authorization cannot leave a stale path admitted.
106
125
  for (const other of fileParentReadCandidates(configuration, operation, fields, binding, current)) {
@@ -1 +1 @@
1
- {"version":3,"file":"file-parent-read-context.backend.js","sourceRoot":"","sources":["../../../../src/files/utils/file-parent-read-context.backend.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Request } from 'express';\nimport {\n CoreResourceOperation, ErrorCustomMessageReference, ErrorType, ResourceOperationVariantType, ResourcePrimaryScope,\n PRIMARY_SCOPE_TO_CORE_RESOURCE_TYPE, PRIMARY_SCOPE_TO_FIELD_IDENTIFIER, ResourcesConfigOperationsUrlsBuilderUtils,\n Resources_SharedUtils, isWildoBackendError,\n type AnyResourceConfiguration, type ResourceConfiguration_Operation, type ResourceConfiguration_Operation_UrlInitiatorInfo, type ResourceType,\n} from '@wildo-ai/saas-models';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { AuthorizationsBackendService } from '~wildo-backend-lib/security/authorizations/services/authorizations.backend.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { FileFieldDetectionBackendService } from '../services/file-field-detection.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { FileShareBinding } from './file-share-binding.backend';\nimport { fileFieldContainsFileId } from './file-field-schema-path.backend.utils';\n\nexport interface FileParentReadDependencies {\n resourcesRegistry: ResourcesRegistryBackendService;\n repositoriesRegistry: RepositoriesRegistryHandlerBackendService;\n executionContextCreator: ExecutionContextCreatorBackendService;\n authorizationsService: AuthorizationsBackendService;\n errorBuilder: ErrorBuilderBackendService;\n fileFieldDetection: FileFieldDetectionBackendService;\n}\n\nexport interface FileParentReadCandidate {\n initiatorInfo: ResourceConfiguration_Operation_UrlInitiatorInfo;\n params: Record<string, string>;\n}\n\n/** Persisted FK values can be Mongo ObjectIds or SQL strings; populated objects are not identities. */\nfunction persistedIds(value: unknown): string[] {\n if (Array.isArray(value)) return [...new Set(value.flatMap(persistedIds))];\n if (typeof value === 'string' && value.length > 0) return [value];\n if (value && typeof value === 'object' && '_bsontype' in value && value._bsontype === 'ObjectId'\n && 'toHexString' in value && typeof value.toHexString === 'function') return [value.toHexString()];\n return [];\n}\n\n/**\n * Derive only routes actually declared by the resource's READ operation. Required context comes\n * from the target row's compiled FK, never caller-supplied guesses or a fabricated shorter route.\n * Arrays enumerate genuine alternatives lazily: a caller can be allowed through its second parent.\n */\nexport function* fileParentReadCandidates(\n configuration: AnyResourceConfiguration,\n operation: ResourceConfiguration_Operation<any, any, any>,\n fieldIdentifiers: Record<string, string>,\n binding: FileShareBinding,\n parent: Record<string, unknown>,\n): Generator<FileParentReadCandidate> {\n if (operation.variantType !== ResourceOperationVariantType.API_CALL) return;\n const edges = ResourcesConfigOperationsUrlsBuilderUtils.getUrlAddressableParentRelationships(configuration, fieldIdentifiers, operation.resourceRelationships)\n .filter(edge => !edge.urlOperationScope || edge.urlOperationScope.includes(CoreResourceOperation.READ));\n const scopeField = PRIMARY_SCOPE_TO_FIELD_IDENTIFIER[binding.primaryScope];\n const scopeId = binding.primaryScope === ResourcePrimaryScope.APPLICATION ? binding.applicationId\n : binding.primaryScope === ResourcePrimaryScope.ORGANIZATIONS ? binding.organizationId : binding.userId;\n for (const initiatorInfo of [...operation.initiatorInfos].sort((a, b) => a.parameters.length - b.parameters.length)) {\n const values = initiatorInfo.parameters.map(parameter => {\n if (parameter.scopeViaJunction) return []; // Synthetic peer-through-junction routes are SEARCH/LIST only.\n if (!parameter.relationshipField && parameter.resourceType === binding.resourceType && parameter.fieldIdentifier === configuration.resourceFieldIdentifier) {\n return [binding.resourceId];\n }\n if (!parameter.relationshipField && parameter.resourceType === PRIMARY_SCOPE_TO_CORE_RESOURCE_TYPE[binding.primaryScope] && parameter.fieldIdentifier === scopeField) {\n return persistedIds(scopeId);\n }\n return [...new Set(edges.flatMap(edge => {\n if (edge.resourceType1 !== parameter.resourceType || edge.foreignKeyField !== parameter.relationshipField\n || (edge.foreignKeyField ?? fieldIdentifiers[edge.resourceType1]) !== parameter.fieldIdentifier) return [];\n const fk = Resources_SharedUtils.ensureCompiledRelationship(edge, fieldIdentifiers).resolvedSemantics.persistence.foreignKey;\n if (!fk || fk.holderResourceType !== binding.resourceType) return [];\n return persistedIds(parent[fk.fieldIdentifier]);\n }))];\n });\n function* combinations(index: number, params: Record<string, string>): Generator<Record<string, string>> {\n if (index === values.length) { yield params; return; }\n const key = initiatorInfo.parameters[index].fieldIdentifier;\n for (const value of values[index]) {\n if (params[key] !== undefined && params[key] !== value) continue;\n yield* combinations(index + 1, { ...params, [key]: value });\n }\n }\n for (const params of combinations(0, {})) yield { initiatorInfo, params };\n }\n}\n\n/**\n * Resolve routing evidence privately, then re-enter the real request authentication boundary.\n * The infrastructure lookup is NOT authority: only a fresh parent READ context plus addressed\n * authorization and a scoped current-record read can admit a file. Never reuse a FILES subcall\n * context here: that misses operation-specific delegated credentials and token policies.\n */\nexport async function authorizeFileParentRead(\n request: Request,\n binding: FileShareBinding,\n dependencies: FileParentReadDependencies,\n): Promise<ExecutionContext<any>> {\n const { resourcesRegistry, repositoriesRegistry, executionContextCreator, authorizationsService, errorBuilder, fileFieldDetection } = dependencies;\n const notFound = () => errorBuilder.buildError(ErrorType.NOT_FOUND, undefined, {\n customMessageReference: ErrorCustomMessageReference.FILE_NOT_FOUND, context: { fileId: binding.fileId },\n });\n const resourceType = binding.resourceType as ResourceType;\n const configuration = resourcesRegistry.getResourceConfiguration(resourceType);\n if (configuration.resourcePrimaryScope !== binding.primaryScope || !fileFieldDetection.getFileFieldMetadata(resourceType, binding.fieldName)\n || !resourcesRegistry.hasOperationPathDefault(resourceType, CoreResourceOperation.READ)) throw notFound();\n const operation = resourcesRegistry.getOperationFromPath(resourcesRegistry.getOperationPathDefault(resourceType, CoreResourceOperation.READ));\n const scopeField = PRIMARY_SCOPE_TO_FIELD_IDENTIFIER[binding.primaryScope];\n const scopeId = binding.primaryScope === ResourcePrimaryScope.APPLICATION ? binding.applicationId\n : binding.primaryScope === ResourcePrimaryScope.ORGANIZATIONS ? binding.organizationId : binding.userId;\n const scopePath = configuration.resourceFieldIdentifier === scopeField ? '_id' : scopeField;\n if (scopePath === '_id' && binding.resourceId !== scopeId) throw notFound();\n // No caller-visible fields escape this exact key+scope, retention-hidden bootstrap. In particular\n // it does not borrow a fabricated unit-narrowing stamp before target authorization can establish one.\n const parent = await repositoriesRegistry.readUnscopedByKey<Record<string, unknown>>(resourceType, { _id: binding.resourceId, [scopePath]: scopeId });\n if (!parent || !fileFieldContainsFileId(parent, binding.fieldName, binding.fileId)) throw notFound();\n const fields = resourcesRegistry.getAllResourceFieldIdentifiers();\n for (const candidate of fileParentReadCandidates(configuration, operation, fields, binding, parent)) {\n // Preserve Express getters/prototype and every credential/coherence source. The private view\n // changes only route parameters; original URL/method remain truthful for diagnostics.\n const requestView = Object.create(request) as Request;\n Object.defineProperty(requestView, 'params', { value: candidate.params, enumerable: true });\n try {\n // assurance-control: WILDO.IDENTITY.DELEGATED_AUTHORIZATION — original credentials authorize the owning record's exact READ operation.\n const context = await executionContextCreator.createExecutionContextFromRequest(requestView, operation, candidate.initiatorInfo);\n await authorizationsService.authorizeInController(binding.resourceId, context);\n const current = await repositoriesRegistry.getRepositoryOrThrow(resourceType, context)\n .readForInternalScan<Record<string, unknown>>(context, { _id: binding.resourceId });\n if (!current || !fileFieldContainsFileId(current, binding.fieldName, binding.fileId)) continue;\n // Parent FK changes between bootstrap and authorization cannot leave a stale path admitted.\n for (const other of fileParentReadCandidates(configuration, operation, fields, binding, current)) {\n if (other.initiatorInfo === candidate.initiatorInfo && Object.keys(candidate.params).every(key => other.params[key] === candidate.params[key])) return context;\n }\n } catch (error) {\n if (isWildoBackendError(error) && (error.type === ErrorType.AUTHENTICATION || error.type === ErrorType.AUTHORIZATION\n || error.customMessageReference === ErrorCustomMessageReference.API_CALL_INITIATOR_PARAMETER_INCONSISTENT\n || (error.type === ErrorType.NOT_FOUND && error.customMessageReference === ErrorCustomMessageReference.AUTHORIZATIONS_VALIDATION_FAILED))) continue;\n throw error;\n }\n }\n throw notFound();\n}\n"]}
1
+ {"version":3,"file":"file-parent-read-context.backend.js","sourceRoot":"","sources":["../../../../src/files/utils/file-parent-read-context.backend.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Request } from 'express';\nimport {\n CoreResourceOperation, ErrorCustomMessageReference, ErrorType, ResourceOperationVariantType, ResourcePrimaryScope,\n PRIMARY_SCOPE_TO_CORE_RESOURCE_TYPE, PRIMARY_SCOPE_TO_FIELD_IDENTIFIER, ResourcesConfigOperationsUrlsBuilderUtils,\n Resources_SharedUtils, isWildoBackendError,\n type AnyResourceConfiguration, type ResourceConfiguration_Operation, type ResourceConfiguration_Operation_UrlInitiatorInfo, type ResourceType,\n} from '@wildo-ai/saas-models';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { ExecutionContextCreatorBackendService } from '~wildo-backend-lib/runtime/services/execution-context-creator.backend.service';\nimport type { AuthorizationsBackendService } from '~wildo-backend-lib/security/authorizations/services/authorizations.backend.service';\nimport type { ErrorBuilderBackendService } from '~wildo-backend-lib/errors/services/error-builder.backend.service';\nimport type { FileFieldDetectionBackendService } from '../services/file-field-detection.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport type { FileShareBinding } from './file-share-binding.backend';\nimport { fileFieldContainsFileId } from './file-field-schema-path.backend.utils';\n\nexport interface FileParentReadDependencies {\n resourcesRegistry: ResourcesRegistryBackendService;\n repositoriesRegistry: RepositoriesRegistryHandlerBackendService;\n executionContextCreator: ExecutionContextCreatorBackendService;\n authorizationsService: AuthorizationsBackendService;\n errorBuilder: ErrorBuilderBackendService;\n fileFieldDetection: FileFieldDetectionBackendService;\n}\n\n/**\n * The record a caller is asked to be able to READ, and the scope it lives in: what both a file's parent (#file shares)\n * and an approval seal's subject (#2913) are authorized through. The scope ids come from where the record was found,\n * never from the caller: they only shape the routes the record's READ is tried through, and each route is then\n * authorized with the caller's own credentials.\n */\nexport interface RecordReadBinding {\n readonly resourceType: string;\n readonly resourceId: string;\n readonly primaryScope: ResourcePrimaryScope;\n readonly applicationId: string;\n readonly organizationId?: string | null;\n readonly userId?: string | null;\n}\n\nexport interface FileParentReadCandidate {\n initiatorInfo: ResourceConfiguration_Operation_UrlInitiatorInfo;\n params: Record<string, string>;\n}\n\n/** Persisted FK values can be Mongo ObjectIds or SQL strings; populated objects are not identities. */\nfunction persistedIds(value: unknown): string[] {\n if (Array.isArray(value)) return [...new Set(value.flatMap(persistedIds))];\n if (typeof value === 'string' && value.length > 0) return [value];\n if (value && typeof value === 'object' && '_bsontype' in value && value._bsontype === 'ObjectId'\n && 'toHexString' in value && typeof value.toHexString === 'function') return [value.toHexString()];\n return [];\n}\n\n/**\n * Derive only routes actually declared by the resource's READ operation. Required context comes\n * from the target row's compiled FK, never caller-supplied guesses or a fabricated shorter route.\n * Arrays enumerate genuine alternatives lazily: a caller can be allowed through its second parent.\n */\nexport function* fileParentReadCandidates(\n configuration: AnyResourceConfiguration,\n operation: ResourceConfiguration_Operation<any, any, any>,\n fieldIdentifiers: Record<string, string>,\n binding: RecordReadBinding,\n parent: Record<string, unknown>,\n): Generator<FileParentReadCandidate> {\n if (operation.variantType !== ResourceOperationVariantType.API_CALL) return;\n const edges = ResourcesConfigOperationsUrlsBuilderUtils.getUrlAddressableParentRelationships(configuration, fieldIdentifiers, operation.resourceRelationships)\n .filter(edge => !edge.urlOperationScope || edge.urlOperationScope.includes(CoreResourceOperation.READ));\n const scopeField = PRIMARY_SCOPE_TO_FIELD_IDENTIFIER[binding.primaryScope];\n const scopeId = binding.primaryScope === ResourcePrimaryScope.APPLICATION ? binding.applicationId\n : binding.primaryScope === ResourcePrimaryScope.ORGANIZATIONS ? binding.organizationId : binding.userId;\n for (const initiatorInfo of [...operation.initiatorInfos].sort((a, b) => a.parameters.length - b.parameters.length)) {\n const values = initiatorInfo.parameters.map(parameter => {\n if (parameter.scopeViaJunction) return []; // Synthetic peer-through-junction routes are SEARCH/LIST only.\n if (!parameter.relationshipField && parameter.resourceType === binding.resourceType && parameter.fieldIdentifier === configuration.resourceFieldIdentifier) {\n return [binding.resourceId];\n }\n if (!parameter.relationshipField && parameter.resourceType === PRIMARY_SCOPE_TO_CORE_RESOURCE_TYPE[binding.primaryScope] && parameter.fieldIdentifier === scopeField) {\n return persistedIds(scopeId);\n }\n return [...new Set(edges.flatMap(edge => {\n if (edge.resourceType1 !== parameter.resourceType || edge.foreignKeyField !== parameter.relationshipField\n || (edge.foreignKeyField ?? fieldIdentifiers[edge.resourceType1]) !== parameter.fieldIdentifier) return [];\n const fk = Resources_SharedUtils.ensureCompiledRelationship(edge, fieldIdentifiers).resolvedSemantics.persistence.foreignKey;\n if (!fk || fk.holderResourceType !== binding.resourceType) return [];\n return persistedIds(parent[fk.fieldIdentifier]);\n }))];\n });\n function* combinations(index: number, params: Record<string, string>): Generator<Record<string, string>> {\n if (index === values.length) { yield params; return; }\n const key = initiatorInfo.parameters[index].fieldIdentifier;\n for (const value of values[index]) {\n if (params[key] !== undefined && params[key] !== value) continue;\n yield* combinations(index + 1, { ...params, [key]: value });\n }\n }\n for (const params of combinations(0, {})) yield { initiatorInfo, params };\n }\n}\n\n/**\n * Resolve routing evidence privately, then re-enter the real request authentication boundary.\n * The infrastructure lookup is NOT authority: only a fresh parent READ context plus addressed\n * authorization and a scoped current-record read can admit a file. Never reuse a FILES subcall\n * context here: that misses operation-specific delegated credentials and token policies.\n */\nexport async function authorizeFileParentRead(\n request: Request,\n binding: FileShareBinding,\n dependencies: FileParentReadDependencies,\n): Promise<ExecutionContext<any>> {\n const { resourcesRegistry, errorBuilder, fileFieldDetection } = dependencies;\n const notFound = () => errorBuilder.buildError(ErrorType.NOT_FOUND, undefined, {\n customMessageReference: ErrorCustomMessageReference.FILE_NOT_FOUND, context: { fileId: binding.fileId },\n });\n if (resourcesRegistry.getResourceConfiguration(binding.resourceType as ResourceType).resourcePrimaryScope !== binding.primaryScope\n || !fileFieldDetection.getFileFieldMetadata(binding.resourceType as ResourceType, binding.fieldName)) throw notFound();\n return authorizeRecordReadAsCaller(request, binding, (row) => fileFieldContainsFileId(row, binding.fieldName, binding.fileId), dependencies, notFound);\n}\n\n/**\n * Admit a caller to something that belongs to ONE record — a file in its field, an approval seal it stores (#2913) —\n * exactly when the record's own READ operation admits them, with their own credentials, and the record (as read in that\n * caller's scope) still `holds` the thing. Every refusal is `notFound()`, so a caller learns nothing about a record they\n * may not read.\n *\n * The routing is derived only from routes the READ operation declares, filled from the record's own scope and foreign\n * keys (`fileParentReadCandidates`); the infrastructure read that finds them is NOT authority. Answers the execution\n * context the admitted route built.\n */\nexport async function authorizeRecordReadAsCaller(\n request: Request,\n binding: RecordReadBinding,\n holds: (row: Record<string, unknown>) => boolean,\n dependencies: Pick<FileParentReadDependencies, 'resourcesRegistry' | 'repositoriesRegistry' | 'executionContextCreator' | 'authorizationsService'>,\n notFound: () => unknown,\n): Promise<ExecutionContext<any>> {\n const { resourcesRegistry, repositoriesRegistry, executionContextCreator, authorizationsService } = dependencies;\n const resourceType = binding.resourceType as ResourceType;\n const configuration = resourcesRegistry.getResourceConfiguration(resourceType);\n if (!configuration || configuration.resourcePrimaryScope !== binding.primaryScope\n || !resourcesRegistry.hasOperationPathDefault(resourceType, CoreResourceOperation.READ)) throw notFound();\n const operation = resourcesRegistry.getOperationFromPath(resourcesRegistry.getOperationPathDefault(resourceType, CoreResourceOperation.READ));\n const scopeField = PRIMARY_SCOPE_TO_FIELD_IDENTIFIER[binding.primaryScope];\n const scopeId = binding.primaryScope === ResourcePrimaryScope.APPLICATION ? binding.applicationId\n : binding.primaryScope === ResourcePrimaryScope.ORGANIZATIONS ? binding.organizationId : binding.userId;\n if (!scopeId) throw notFound();\n const scopePath = configuration.resourceFieldIdentifier === scopeField ? '_id' : scopeField;\n if (scopePath === '_id' && binding.resourceId !== scopeId) throw notFound();\n // No caller-visible fields escape this exact key+scope, retention-hidden bootstrap. In particular\n // it does not borrow a fabricated unit-narrowing stamp before target authorization can establish one.\n const parent = await repositoriesRegistry.readUnscopedByKey<Record<string, unknown>>(resourceType, { _id: binding.resourceId, [scopePath]: scopeId });\n if (!parent || !holds(parent)) throw notFound();\n const fields = resourcesRegistry.getAllResourceFieldIdentifiers();\n for (const candidate of fileParentReadCandidates(configuration, operation, fields, binding, parent)) {\n // Preserve Express getters/prototype and every credential/coherence source. The private view\n // changes only route parameters; original URL/method remain truthful for diagnostics.\n const requestView = Object.create(request) as Request;\n Object.defineProperty(requestView, 'params', { value: candidate.params, enumerable: true });\n try {\n // assurance-control: WILDO.IDENTITY.DELEGATED_AUTHORIZATION — original credentials authorize the owning record's exact READ operation.\n const context = await executionContextCreator.createExecutionContextFromRequest(requestView, operation, candidate.initiatorInfo);\n await authorizationsService.authorizeInController(binding.resourceId, context);\n const current = await repositoriesRegistry.getRepositoryOrThrow(resourceType, context)\n .readForInternalScan<Record<string, unknown>>(context, { _id: binding.resourceId });\n if (!current || !holds(current)) continue;\n // Parent FK changes between bootstrap and authorization cannot leave a stale path admitted.\n for (const other of fileParentReadCandidates(configuration, operation, fields, binding, current)) {\n if (other.initiatorInfo === candidate.initiatorInfo && Object.keys(candidate.params).every(key => other.params[key] === candidate.params[key])) return context;\n }\n } catch (error) {\n if (isWildoBackendError(error) && (error.type === ErrorType.AUTHENTICATION || error.type === ErrorType.AUTHORIZATION\n || error.customMessageReference === ErrorCustomMessageReference.API_CALL_INITIATOR_PARAMETER_INCONSISTENT\n || (error.type === ErrorType.NOT_FOUND && error.customMessageReference === ErrorCustomMessageReference.AUTHORIZATIONS_VALIDATION_FAILED))) continue;\n throw error;\n }\n }\n throw notFound();\n}\n"]}
@@ -17,6 +17,17 @@
17
17
  * Fail closed at use, warn at boot: the report never throws and never stops startup. The remedy (select a classifier for
18
18
  * this environment, or remove the declaration) is an edit to configuration, and a refused boot would also take down
19
19
  * everything the application serves that does not need a classifier.
20
+ *
21
+ * ## An environment may declare that its agents run unguarded
22
+ *
23
+ * `agentContentGuardrails: { withoutClassifier: RUN_UNGUARDED, reason }` in `wildo.infra.<env>.config.ts` (see
24
+ * `EnvironmentAgentContentGuardrailsSchema` in `@wildo-ai/saas-models`). Where it is declared and NO selected classifier
25
+ * offers a guardrail, the predicate below still reports the gap, and marks it `runsUnguarded`: the agent's turn then runs
26
+ * without that guardrail, and the boot report names the agent as UNGUARDED (with the environment's reason) instead of as
27
+ * refusing. "No classifier" means none is PRESENT for the guardrail (`ContentSafetyBackendService.classifierPresentFor`):
28
+ * none declared, the selected one does not offer it, or its credentials are not authored in this environment. A
29
+ * classifier that is there and cannot be used (declared and not loaded, a category it does not assess) is never waived,
30
+ * and one that fails at call time (a key set and refused, an outage) still withholds: those are failures.
20
31
  */
21
32
  import { ContentSafety_HarmCategory } from '@wildo-ai/external-connectors-models';
22
33
  import { type FlowsActors_Agent } from '@wildo-ai/saas-models';
@@ -48,6 +59,21 @@ export interface ContentGuardrailClassifierUnavailability {
48
59
  readonly gap: ContentGuardrailClassifierGap;
49
60
  /** The reason, in the runtime's words: it is the clause after "cannot be screened:" in the refusal. */
50
61
  readonly reason: string;
62
+ /**
63
+ * Set when this environment DECLARED that its agents run unguarded where no classifier serves them
64
+ * (`agentContentGuardrails: { withoutClassifier: RUN_UNGUARDED, reason }`), and none is present for this guardrail:
65
+ * none declared, the selected one does not offer it, or its credentials are not authored in this environment. An
66
+ * agent's own turn then runs without the guardrail instead of being refused. Never set for a classifier that is there
67
+ * and cannot be used (declared and not loaded, a category it does not assess, a broken contract), nor for a process
68
+ * missing the service: those are failures, not the absence the environment declared.
69
+ *
70
+ * An organization's administrator still cannot switch the guardrail ON here (`classifierRefusalOf` refuses on any
71
+ * unavailability): asking for a guardrail nothing can provide would read as a protection that does not exist.
72
+ */
73
+ readonly runsUnguarded?: {
74
+ /** The environment's own `reason`, printed beside every agent it leaves unguarded. */
75
+ readonly declaredReason: string;
76
+ };
51
77
  }
52
78
  /**
53
79
  * Why `contentSafety` cannot serve `guardrail`, or `undefined` when it can. The ONE predicate: the runtime refuses an
@@ -1 +1 @@
1
- {"version":3,"file":"classifier-availability.backend.utils.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/classifier-availability.backend.utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classifier-availability.backend.utils.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/content-guardrails/classifier-availability.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,0BAA0B,EAAsC,MAAM,sCAAsC,CAAC;AACtH,OAAO,EAML,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,KAAK,2BAA2B,EAAE,MAAM,+EAA+E,CAAC;AAEjI,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8DAA8D,CAAC;AAElG,gGAAgG;AAChG,oBAAY,gCAAgC;IAC1C,2GAA2G;IAC3G,gBAAgB,oBAAoB;IACpC,oGAAoG;IACpG,iBAAiB,qBAAqB;CACvC;AAED;;;GAGG;AACH,oBAAY,6BAA6B;IACvC,oHAAoH;IACpH,yBAAyB,8BAA8B;IACvD,sHAAsH;IACtH,yBAAyB,8BAA8B;IACvD,wHAAwH;IACxH,oBAAoB,yBAAyB;IAC7C,8HAA8H;IAC9H,8BAA8B,mCAAmC;CAClE;AAED,yFAAyF;AACzF,MAAM,WAAW,wCAAwC;IACvD,QAAQ,CAAC,GAAG,EAAE,6BAA6B,CAAC;IAC5C,uGAAuG;IACvG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE;QACvB,sFAAsF;QACtF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;KACjC,CAAC;CACH;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,2BAA2B,GAAG,SAAS,EACtD,SAAS,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,gCAAgC,CAAC,gBAAgB,CAAA;CAAE,GAAG;IAChF,QAAQ,CAAC,IAAI,EAAE,gCAAgC,CAAC,iBAAiB,CAAC;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,0BAA0B,EAAE,CAAC;CAC5D,EACD,MAAM,SAAiB,GACtB,wCAAwC,GAAG,SAAS,CAQtD;AAkDD,yEAAyE;AACzE,MAAM,WAAW,+BAAgC,SAAQ,wCAAwC;IAC/F,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,gCAAgC,CAAC;IACrD,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,kGAAkG;AAClG,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,6BAA6B,EAAE,SAAS,EAAE,gCAAgC,GAAG,MAAM,CAoB3I;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,mBAAmB,CAAC,EAC3D,aAAa,EAAE,2BAA2B,GAAG,SAAS,GACrD,+BAA+B,EAAE,CAenC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sCAAsC,CAAC,KAAK,EAAE;IAC5D,2HAA2H;IAC3H,QAAQ,CAAC,UAAU,EAAE,MAAM,SAAS,iBAAiB,EAAE,CAAC;IACxD,4GAA4G;IAC5G,QAAQ,CAAC,oBAAoB,EAAE,MAAM,2BAA2B,GAAG,SAAS,CAAC;IAC7E,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CACxD,GAAG,+BAA+B,EAAE,CAuCpC;AAoDD,wFAAwF;AACxF,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAA;KAAE,EAAE,GAAG,IAAI,CAAC;CACjG;AAED;;;GAGG;AACH,eAAO,MAAM,+CAA+C,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE5F,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,gDAAgD,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE7F,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iDAAiD,CAAC,KAAK,EAAE;IAC7E,QAAQ,CAAC,oBAAoB,EAAE,MAAM,2BAA2B,GAAG,SAAS,CAAC;IAC7E,iFAAiF;IACjF,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvF,4HAA4H;IAC5H,QAAQ,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC,SAAS,+BAA+B,EAAE,CAAC,CAAC;IAC1H,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC;CACxD,GAAG,OAAO,CAAC,MAAM,CAAC,CA6ClB"}