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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/dist/esm/base-classes/models/manual-controllers.backend.definition.d.ts.map +1 -1
  2. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js +2 -0
  3. package/dist/esm/base-classes/models/manual-controllers.backend.definition.js.map +1 -1
  4. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts +4 -0
  5. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.d.ts.map +1 -1
  6. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js +20 -5
  7. package/dist/esm/base-classes/services/repositories/stored-field-omission.backend.js.map +1 -1
  8. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts +3 -0
  9. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.d.ts.map +1 -1
  10. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js +10 -1
  11. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation-registry.backend.service.js.map +1 -1
  12. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts +22 -0
  13. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.d.ts.map +1 -1
  14. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js +25 -1
  15. package/dist/esm/base-classes/services/services/resource-operation-custom-implementation.factory.backend.js.map +1 -1
  16. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts +38 -3
  17. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.d.ts.map +1 -1
  18. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js +68 -5
  19. package/dist/esm/base-classes/services/services/resource-operation-transaction-persistence.backend.utils.js.map +1 -1
  20. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts +2 -2
  21. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.d.ts.map +1 -1
  22. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js +6 -3
  23. package/dist/esm/base-classes/services/services/resource-status-transition.custom-impl.backend.service.js.map +1 -1
  24. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts +83 -0
  25. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.d.ts.map +1 -1
  26. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js +217 -14
  27. package/dist/esm/base-classes/services/services/services-registry-handler.backend.service.js.map +1 -1
  28. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts +32 -0
  29. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.d.ts.map +1 -0
  30. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js +36 -0
  31. package/dist/esm/compliance/approval-seals/approval-seal-currency.backend.js.map +1 -0
  32. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts +38 -0
  33. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.d.ts.map +1 -0
  34. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js +83 -0
  35. package/dist/esm/compliance/approval-seals/approval-seal-on-record.backend.js.map +1 -0
  36. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts +36 -0
  37. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.d.ts.map +1 -0
  38. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js +51 -0
  39. package/dist/esm/compliance/approval-seals/approval-seal-presentation-read.backend.js.map +1 -0
  40. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts +46 -0
  41. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.d.ts.map +1 -1
  42. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js +68 -0
  43. package/dist/esm/compliance/approval-seals/approval-seal-relay-store.backend.js.map +1 -1
  44. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts +27 -0
  45. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.d.ts.map +1 -1
  46. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js +42 -3
  47. package/dist/esm/compliance/approval-seals/approval-seal-store.backend.js.map +1 -1
  48. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts +26 -1
  49. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.d.ts.map +1 -1
  50. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js +10 -0
  51. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.contracts.js.map +1 -1
  52. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts +10 -1
  53. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.d.ts.map +1 -1
  54. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js +60 -28
  55. package/dist/esm/compliance/approval-seals/approval-seals-admin.backend.controller.js.map +1 -1
  56. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts +90 -0
  57. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.d.ts.map +1 -0
  58. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js +373 -0
  59. package/dist/esm/compliance/approval-seals/approval-seals-on-record.backend.controller.js.map +1 -0
  60. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts +29 -2
  61. package/dist/esm/compliance/approval-seals/decision-presentation.backend.d.ts.map +1 -1
  62. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js +40 -3
  63. package/dist/esm/compliance/approval-seals/decision-presentation.backend.js.map +1 -1
  64. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.d.ts.map +1 -1
  65. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js +34 -6
  66. package/dist/esm/compliance/electronic-signatures/pdf-signature-structure.backend.js.map +1 -1
  67. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts +30 -6
  68. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.d.ts.map +1 -1
  69. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js +67 -22
  70. package/dist/esm/compliance/electronic-signatures/signature-request-evidence-files.backend.js.map +1 -1
  71. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.d.ts.map +1 -1
  72. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js +18 -1
  73. package/dist/esm/compliance/electronic-signatures/signature-request-poll.batch.backend.service.js.map +1 -1
  74. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts +66 -1
  75. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.d.ts.map +1 -1
  76. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js +161 -14
  77. package/dist/esm/compliance/electronic-signatures/signature-requests.backend.service.js.map +1 -1
  78. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts +47 -0
  79. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.d.ts.map +1 -1
  80. package/dist/esm/compliance/electronic-signatures/signed-document-validation.backend.js.map +1 -1
  81. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts +27 -2
  82. package/dist/esm/external-providers/services/content-safety.backend.service.d.ts.map +1 -1
  83. package/dist/esm/external-providers/services/content-safety.backend.service.js +46 -1
  84. package/dist/esm/external-providers/services/content-safety.backend.service.js.map +1 -1
  85. package/dist/esm/external-providers/services/embeddings.backend.service.d.ts.map +1 -1
  86. package/dist/esm/external-providers/services/embeddings.backend.service.js +2 -0
  87. package/dist/esm/external-providers/services/embeddings.backend.service.js.map +1 -1
  88. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +11 -0
  89. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  90. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +23 -0
  91. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  92. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts +19 -1
  93. package/dist/esm/external-providers/services/provider-service-account-token.backend.d.ts.map +1 -1
  94. package/dist/esm/external-providers/services/provider-service-account-token.backend.js +41 -1
  95. package/dist/esm/external-providers/services/provider-service-account-token.backend.js.map +1 -1
  96. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts +27 -2
  97. package/dist/esm/files/utils/file-parent-read-context.backend.d.ts.map +1 -1
  98. package/dist/esm/files/utils/file-parent-read-context.backend.js +23 -4
  99. package/dist/esm/files/utils/file-parent-read-context.backend.js.map +1 -1
  100. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts +26 -0
  101. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.d.ts.map +1 -1
  102. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js +100 -8
  103. package/dist/esm/flows-actors/content-guardrails/classifier-availability.backend.utils.js.map +1 -1
  104. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts +3 -1
  105. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.d.ts.map +1 -1
  106. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js +8 -2
  107. package/dist/esm/flows-actors/content-guardrails/record-owner-policy.backend.js.map +1 -1
  108. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts +43 -0
  109. package/dist/esm/flows-actors/models/function-tools.backend.definitions.d.ts.map +1 -1
  110. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js +37 -0
  111. package/dist/esm/flows-actors/models/function-tools.backend.definitions.js.map +1 -1
  112. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts +7 -0
  113. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.d.ts.map +1 -1
  114. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js +8 -3
  115. package/dist/esm/flows-actors/services/agent-work-decisions.backend.service.js.map +1 -1
  116. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +31 -6
  117. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  118. package/dist/esm/flows-actors/services/agents.backend.service.js +78 -30
  119. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  120. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.d.ts.map +1 -1
  121. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js +4 -0
  122. package/dist/esm/flows-actors/services/autonomous-agent-turn.backend.service.js.map +1 -1
  123. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts +28 -2
  124. package/dist/esm/flows-actors/services/conversational-execution.backend.service.d.ts.map +1 -1
  125. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js +132 -22
  126. package/dist/esm/flows-actors/services/conversational-execution.backend.service.js.map +1 -1
  127. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.d.ts.map +1 -1
  128. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js +12 -8
  129. package/dist/esm/flows-actors/services/flow-actor-executions.custom-impl.backend.service.js.map +1 -1
  130. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts +5 -0
  131. package/dist/esm/flows-actors/services/flows-actors-registry.service.d.ts.map +1 -1
  132. package/dist/esm/flows-actors/services/flows-actors-registry.service.js +18 -2
  133. package/dist/esm/flows-actors/services/flows-actors-registry.service.js.map +1 -1
  134. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +33 -0
  135. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  136. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +58 -0
  137. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  138. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts +12 -1
  139. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.d.ts.map +1 -1
  140. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js +23 -4
  141. package/dist/esm/inbound/services/inbound-delivery-dispatch.backend.service.js.map +1 -1
  142. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts +12 -1
  143. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.d.ts.map +1 -1
  144. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js +55 -17
  145. package/dist/esm/inbound/services/inbound-delivery-receiver.backend.service.js.map +1 -1
  146. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts +22 -1
  147. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.d.ts.map +1 -1
  148. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js +52 -9
  149. package/dist/esm/inbound/services/inbound-delivery-store.backend.service.js.map +1 -1
  150. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts +79 -0
  151. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.d.ts.map +1 -0
  152. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js +211 -0
  153. package/dist/esm/inbound/services/inbound-delivery-stored-body.backend.service.js.map +1 -0
  154. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts +2 -2
  155. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.d.ts.map +1 -1
  156. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js +9 -1
  157. package/dist/esm/inbound/services/inbound-delivery-subject-erasure-severance.backend.js.map +1 -1
  158. package/dist/esm/index.d.ts +1 -0
  159. package/dist/esm/index.d.ts.map +1 -1
  160. package/dist/esm/index.js +1 -0
  161. package/dist/esm/index.js.map +1 -1
  162. package/dist/esm/inject/models/container.d.ts.map +1 -1
  163. package/dist/esm/inject/models/container.js +6 -0
  164. package/dist/esm/inject/models/container.js.map +1 -1
  165. package/dist/esm/inject/models/service-types.d.ts +5 -0
  166. package/dist/esm/inject/models/service-types.d.ts.map +1 -1
  167. package/dist/esm/inject/models/service-types.js +3 -0
  168. package/dist/esm/inject/models/service-types.js.map +1 -1
  169. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts +5 -0
  170. package/dist/esm/monitoring/observability/models/observability.backend.schemas.d.ts.map +1 -1
  171. package/dist/esm/monitoring/observability/models/observability.backend.schemas.js.map +1 -1
  172. package/dist/esm/monitoring/observability/services/metrics.service.d.ts +34 -1
  173. package/dist/esm/monitoring/observability/services/metrics.service.d.ts.map +1 -1
  174. package/dist/esm/monitoring/observability/services/metrics.service.js +49 -0
  175. package/dist/esm/monitoring/observability/services/metrics.service.js.map +1 -1
  176. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts +6 -1
  177. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.d.ts.map +1 -1
  178. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js +15 -4
  179. package/dist/esm/notifications/webhooks/controllers/webhook-auto-controller.backend.service.js.map +1 -1
  180. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.d.ts.map +1 -1
  181. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js +3 -1
  182. package/dist/esm/notifications/webhooks/outbound/services/m2m-webhook-delivery-log.custom-impl.backend.service.js.map +1 -1
  183. package/dist/esm/runtime/services/http-server.backend.service.d.ts +3 -1
  184. package/dist/esm/runtime/services/http-server.backend.service.d.ts.map +1 -1
  185. package/dist/esm/runtime/services/http-server.backend.service.js +11 -3
  186. package/dist/esm/runtime/services/http-server.backend.service.js.map +1 -1
  187. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts +22 -0
  188. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.d.ts.map +1 -1
  189. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js +54 -0
  190. package/dist/esm/runtime/services/utils/inbound-endpoint-raw-body.backend.utils.js.map +1 -1
  191. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts +51 -0
  192. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.d.ts.map +1 -1
  193. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js +87 -15
  194. package/dist/esm/security/authentications/services/auth-methods/auth-password-reset.backend.service.js.map +1 -1
  195. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.d.ts.map +1 -1
  196. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js +5 -2
  197. package/dist/esm/security/authentications/services/custom-impls/siem-delivery-dlq.custom-impl.backend.service.js.map +1 -1
  198. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.d.ts.map +1 -1
  199. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js +65 -24
  200. package/dist/esm/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.js.map +1 -1
  201. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts +64 -1
  202. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.d.ts.map +1 -1
  203. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js +84 -2
  204. package/dist/esm/security/authorizations/super-admin-floor.backend.utils.js.map +1 -1
  205. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts +14 -0
  206. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.d.ts.map +1 -1
  207. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js +13 -5
  208. package/dist/esm/security/oauth-clients/oauth-clients.custom-impl.backend.service.js.map +1 -1
  209. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.d.ts.map +1 -1
  210. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js +6 -2
  211. package/dist/esm/users/services/anonymous-consent.custom-impl.backend.service.js.map +1 -1
  212. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts +7 -0
  213. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.d.ts.map +1 -1
  214. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js +65 -20
  215. package/dist/esm/users/services/user-force-password-reset.custom-impl.backend.service.js.map +1 -1
  216. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.d.ts.map +1 -1
  217. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js +11 -4
  218. package/dist/esm/users/services/user-role-administration.custom-impl.backend.service.js.map +1 -1
  219. package/dist/esm/users/services/user-self-custom-implementations.backend.d.ts.map +1 -1
  220. package/dist/esm/users/services/user-self-custom-implementations.backend.js +4 -2
  221. package/dist/esm/users/services/user-self-custom-implementations.backend.js.map +1 -1
  222. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.d.ts.map +1 -1
  223. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js +16 -0
  224. package/dist/esm/users/services/user-super-admin-floor.custom-impl.backend.service.js.map +1 -1
  225. package/dist/tsconfig.build.tsbuildinfo +1 -1
  226. package/package.json +10 -10
@@ -1 +1 @@
1
- {"version":3,"file":"sso-config-domain-verification.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../src/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SSO Config — domain-ownership and sign-in routing operations (#424, #2519)\n *\n * Five public operations that turn enterprise domain routing from an out-of-band database write\n * into a self-service admin flow; one platform operator's repair (`repairUnreadableConfiguration`, #3345, #3349) for a\n * scope whose configuration no longer reads, and the administrator's list of what does not read (`describeUnreadableFields`):\n *\n * claimDomain → mints a DNS-TXT challenge, records the domain as `pending`, returns the record\n * verifyDomain → resolves the record, records `verified` or `failed`\n * revokeDomain → removes the claim, its status, its nonce and its `ssoEnabledDomains` entry\n * enableDomainSso → opts a VERIFIED domain into sign-in routing (`ssoEnabledDomains`)\n * disableDomainSso → withdraws that opt-in, keeping the proof\n *\n * The last two exist because #1226 made routing need BOTH proof and the scope's opt-in, and #1804 then\n * let `domains` move only through the first three — which write the proof alone. Until #2519 no\n * organization could turn single sign-on on for its own domain without a database write.\n *\n * ## Why PREFIX, and not OVERRIDE_ALL\n *\n * Each handler computes the new `domains` block and returns it; the framework's own core UPDATE\n * persists it. `OVERRIDE_ALL` returns before the post-operation lane, so it emits NO\n * `RESOURCE_OPERATION_PERFORMED` audit event — and the audit row is the control that makes a\n * privileged configuration change with cross-tenant reach accountable. An operation that granted a\n * tenant SSO routing authority and left no trail would be strictly worse than the database write it\n * replaces, which at least happens where a DBA can see it.\n *\n * ## Where the domain-ownership rules live\n *\n * In `DomainVerificationBackendService`, as pure planners. This file is the door: it resolves the\n * scope, enforces the refusals, and hands the plan to the framework. Nothing here re-implements\n * what a claim or a revocation means.\n */\n\nimport {\n AuthScopeType,\n CoreResourceType,\n DomainVerificationStatus,\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationVariantType,\n SsoConfig_Operations,\n SsoConfig_RepairUnreadableConfigurationRequestDto,\n SsoConfigRepairRefusal,\n SSO_CONFIG_BLOCKS,\n SsoConfigBlock,\n ssoConfigBlockFaults,\n} from '@wildo-ai/saas-models';\nimport type { SsoConfigBase } from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport {\n createResourceCustomServiceImplementation,\n ResourceCustomServiceImplementationHookTransactionPosture,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type {\n DomainVerificationBackendService,\n SsoConfigDomains,\n} from '~wildo-backend-lib/security/authentications/services/admin-config/domain-verification.backend.service';\nimport type { ResourceOperation_CustomImplementation_Utils } from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation-base.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { registerTransactionPostCommitEffect } from '~wildo-backend-lib/databases/models/transaction.shared.schemas';\nimport { DnsLookupUnavailableError } from '~wildo-backend-lib/security/dns/dns-txt-lookup.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport { emitAuthorityChangeAuditWhenDurable } from '~wildo-backend-lib/organizations/services/authority-change-audit.backend.utils';\nimport { planSsoConfigRepair, type SsoConfigRepair } from '~wildo-backend-lib/security/authentications/services/admin-config/sso-config-repair.backend.utils';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { isEnabledSocialOAuth2LoginProvider } from '~wildo-backend-lib/security/authentications/utils/social-oauth2-purpose.backend.utils';\n\n// ── The two scope variants, and how each names its scope ─────────────\n\ninterface SsoConfigScopeVariant {\n readonly resourceType: CoreResourceType;\n readonly scopeType: AuthScopeType;\n readonly scopeField: 'organizationId' | 'applicationId';\n}\n\nconst SSO_CONFIG_SCOPE_VARIANTS: readonly SsoConfigScopeVariant[] = [\n {\n resourceType: CoreResourceType.ORGANIZATION_SSO_CONFIG,\n scopeType: AuthScopeType.ORGANIZATION,\n scopeField: 'organizationId',\n },\n {\n resourceType: CoreResourceType.APPLICATION_SSO_CONFIG,\n scopeType: AuthScopeType.APPLICATION,\n scopeField: 'applicationId',\n },\n];\n\n/**\n * Carries the two values a response needs that the persisted row does not hold, from the PREFIX\n * that computed them to the POSTFIX that shapes the reply.\n *\n * Bounded on purpose. The precedent bridges in this tree (`ROTATE_BRIDGE_BY_TARGET_ID`) delete\n * their entry in the postfix and rely on the postfix always running; a core UPDATE that throws\n * between the two leaks one entry forever. Expiring on write costs one `Date.now()` per call and\n * removes the question.\n */\nconst RESPONSE_BRIDGE_TTL_MS = 60_000;\nconst RESPONSE_BRIDGE = new Map<string, { value: Record<string, unknown>; expiresAt: number }>();\n\n/**\n * Keyed on the REQUEST, not on the row.\n *\n * The postfix receives the persisted row and the execution context — never the request body — so it\n * cannot re-derive which domain the call was about. `correlationId` is minted per request and is\n * the same value in both handlers, which makes the hand-off exact: two admins claiming two domains\n * on the same configuration row at the same instant cannot read each other's response.\n */\nfunction bridgeKey(resourceType: CoreResourceType, operation: string, executionContext: ExecutionContext<any>): string {\n return `${resourceType}|${operation}|${executionContext.correlationId}`;\n}\n\nfunction putBridged(key: string, value: Record<string, unknown>): void {\n const now = Date.now();\n for (const [existingKey, entry] of RESPONSE_BRIDGE) {\n if (entry.expiresAt <= now) RESPONSE_BRIDGE.delete(existingKey);\n }\n RESPONSE_BRIDGE.set(key, { value, expiresAt: now + RESPONSE_BRIDGE_TTL_MS });\n}\n\nfunction takeBridged(key: string): Record<string, unknown> | undefined {\n const entry = RESPONSE_BRIDGE.get(key);\n RESPONSE_BRIDGE.delete(key);\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\n// ── Shared request resolution ────────────────────────────────────────\n\ninterface ResolvedDomainRequest {\n readonly domain: string;\n readonly scopeId: string;\n readonly domains: SsoConfigDomains;\n}\n\n/**\n * The row being updated, its scope id, and the normalised domain.\n *\n * `utils.currentObject` is the pre-image the framework already fetched for this UPDATE, so nothing\n * here re-reads the config. The domain is lowercased HERE, once, because every stored map is keyed\n * on the lowercase form and a second normalisation site is a second place for the two to disagree.\n */\nfunction resolveDomainRequest(\n variant: SsoConfigScopeVariant,\n input: unknown,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): ResolvedDomainRequest {\n const rawDomain = (input as { domain?: unknown } | undefined)?.domain;\n if (typeof rawDomain !== 'string' || rawDomain.trim().length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n context: {\n code: 'SSO_DOMAIN_REQUIRED',\n reason: 'sso_domain_required',\n message: 'Provide `domain`: the DNS hostname this scope is claiming.',\n },\n });\n }\n\n const currentObject = utils.currentObject as (SsoConfigBase & Record<string, unknown>) | undefined;\n const scopeId = currentObject?.[variant.scopeField];\n if (!currentObject?.domains || typeof scopeId !== 'string' || scopeId.length === 0) {\n // The row is addressed by its scope (a one-to-one composition), so a missing scope id means the\n // framework could not resolve the singleton — never that the caller addressed someone else.\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n context: {\n code: 'SSO_CONFIG_SCOPE_UNRESOLVED',\n reason: 'sso_config_scope_unresolved',\n message: 'The SSO configuration row for this scope could not be resolved.',\n resourceType: variant.resourceType,\n },\n });\n }\n\n return { domain: rawDomain.trim().toLowerCase(), scopeId, domains: currentObject.domains };\n}\n\nfunction getDomainVerificationService(container: Container): DomainVerificationBackendService {\n return container.get<DomainVerificationBackendService>(SAAS_SERVICE_TYPES.DomainVerificationService);\n}\n\n/**\n * Refuse when another scope already holds this domain VERIFIED.\n *\n * Run at CLAIM as a helpful early refusal, and again at VERIFY because that is the gate that\n * matters: a claim is not a lock, so another scope can complete its own verification in between.\n * Two scopes verifying at the same moment both still pass this read, which is why a proven domain is then reserved (#3321).\n *\n * **The holder is deliberately not named.** Telling one tenant which other tenant holds a domain\n * discloses a customer's configuration to a stranger who supplied nothing but a hostname. The\n * message says what to do instead — the current holder revokes, and then the claim succeeds — which\n * is the only remedy anyway.\n */\nasync function assertDomainNotHeldElsewhere(\n container: Container,\n variant: SsoConfigScopeVariant,\n scopeId: string,\n domain: string,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): Promise<void> {\n const conflict = await getDomainVerificationService(container)\n .findConflictingScope(variant.scopeType, scopeId, domain);\n if (conflict) throw domainHeldElsewhere(domain, executionContext, utils);\n}\n\n/** The refusal a domain another scope holds answers, from the read above or from the store's reservation (#3321). */\nfunction domainHeldElsewhere(domain: string, executionContext: ExecutionContext<any>, utils: ResourceOperation_CustomImplementation_Utils) {\n return utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_VERIFIED_ELSEWHERE',\n reason: 'sso_domain_verified_elsewhere',\n message:\n 'Another scope holds this domain, verified or being verified. A domain routes sign-ins to exactly one '\n + 'identity provider, so it must be revoked where it is held before it can be claimed here.',\n domain,\n },\n });\n}\n\n// ════════════════════════════════════════════════════════════════════\n// claimDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createClaimDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.CLAIM_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.claimDomain`,\n // #2297: the exclusivity check is a read of OTHER scopes' committed configs (a plain read, which the row lock does not\n // block); planning the claim is pure. Nothing leaves the database.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n await assertDomainNotHeldElsewhere(container, variant, scopeId, domain, executionContext, utils);\n\n const plan = getDomainVerificationService(container).planDomainClaim(domains, domain);\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.CLAIM_DOMAIN, executionContext), {\n domain,\n status: DomainVerificationStatus.PENDING,\n dnsName: plan.dnsName,\n dnsRecordValue: plan.dnsRecordValue,\n });\n\n // The ONLY key returned. The core UPDATE `$set`s what it is given, so returning the whole\n // row here would re-write every other block from a pre-image this handler never validated.\n return { domains: plan.domains };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.CLAIM_DOMAIN, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// verifyDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createVerifyDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.VERIFY_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.verifyDomain`,\n /*\n * #2297: stays outside a transaction. The prefix asks DNS (up to ~10 s, which would hold the row lock, and a retried\n * attempt would ask again and could read another answer), and the domain reservation it takes must AUTOCOMMIT (a\n * unique violation aborts a PostgreSQL transaction, so the loser could not answer its refusal from inside one;\n * `DomainVerificationBackendService.reserveDomain`). Both feed the write. Moving them into a `beforeTransactionalCore`\n * phase is the split that would let this write keep its audit row.\n */\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.STAYS_OUTSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n const service = getDomainVerificationService(container);\n\n const expectedToken = service.getVerificationToken(domains, domain);\n if (!expectedToken) {\n // A claim mints the nonce, so verifying without one is not a failed check — it is a\n // request for a challenge that was never raised. Saying so is what stops an operator\n // publishing a record and waiting for a verification that can never pass.\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_NOT_CLAIMED',\n reason: 'sso_domain_not_claimed',\n message: 'No verification challenge exists for this domain in this scope. Claim it first.',\n domain,\n },\n });\n }\n\n // Re-checked HERE, not only at claim: a claim takes no lock, so another scope may have\n // completed its own verification since. This is the write that confers routing authority\n // and therefore the one that must be exclusive.\n await assertDomainNotHeldElsewhere(container, variant, scopeId, domain, executionContext, utils);\n\n let challenge: { verified: boolean; recordsFound: string[] };\n try {\n challenge = await service.checkDomainChallenge(domain, expectedToken);\n } catch (error) {\n if (error instanceof DnsLookupUnavailableError) {\n // DNS could not be ASKED. That is not a failed check: recording `failed` would tell the\n // administrator their correct record is missing — and on a re-verify would withdraw\n // routing from a domain that is still theirs. Refuse, persist nothing, and say so. The\n // email lane answers its own DNS outage the same way (`EMAIL_DOMAIN_DNS_UNAVAILABLE`).\n throw utils.errorBuilder.buildError(ErrorType.EXTERNAL_SERVICE, executionContext, {\n context: {\n code: 'SSO_DOMAIN_DNS_UNAVAILABLE',\n reason: 'sso_domain_dns_unavailable',\n message: `DNS could not be asked for ${service.verificationDnsName(domain)}. Nothing was changed; try again.`,\n domain,\n },\n });\n }\n throw error;\n }\n const { verified, recordsFound } = challenge;\n // This read and the one above cannot see a verification running beside them; the reservation's unique row can (#3321).\n if (verified && await service.reserveDomain(variant.scopeType, scopeId, domain)) {\n throw domainHeldElsewhere(domain, executionContext, utils);\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.VERIFY_DOMAIN, executionContext), {\n domain,\n status: verified ? DomainVerificationStatus.VERIFIED : DomainVerificationStatus.FAILED,\n dnsName: service.verificationDnsName(domain),\n dnsRecordsFound: recordsFound,\n });\n\n return { domains: service.planVerificationOutcome(domains, domain, verified) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.VERIFY_DOMAIN, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// revokeDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createRevokeDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.REVOKE_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.revokeDomain`,\n // #2297: the prefix is pure, and the reservation's release is registered as a post-commit effect inside a transaction.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n\n const isClaimed = domains.verifiedDomains.includes(domain)\n || domains.domainVerificationStatus?.[domain] !== undefined\n || domains.ssoEnabledDomains.includes(domain);\n if (!isClaimed) {\n /**\n * CONFLICT, not NOT_FOUND — corrected 2026-09-10 after the refusal was driven over HTTP\n * for the first time, and for three independent reasons.\n *\n * **It could not name itself.** `sanitizeErrorForClient` allow-lists a refusal's\n * `context` — and with it the client-branchable `code` — only for VALIDATION, CONFLICT\n * and RATE_LIMIT; every other type has its context stripped whole. So as a NOT_FOUND\n * this answered a bare `not_found` and `SSO_DOMAIN_NOT_CLAIMED` reached no client. A\n * status and a name that cannot both be delivered is not a contract.\n *\n * **Its SIBLING already answers 409 for the same condition.** `verifyDomain` refuses a\n * domain with no challenge as a CONFLICT, eight hundred lines up in this same file. One\n * condition, two verbs, two answers — the shape\n * `.claude/rules/invariant-call-site-enumeration.md` exists for.\n *\n * **And 409 is what the framework's own rule asks for here.**\n * `administrative-continuity-floors.md`: refuse with CONFLICT, never 403 or 400, when\n * the caller IS authorized and the payload IS valid and what forbids the write is the\n * current STATE. The addressed row — the SSO config singleton — exists and resolved;\n * what does not exist is a claim inside it. A 404 on a URL that resolved is also the\n * exact ambiguity issue #542 records against itself: a dispatched 404 and a routing 404\n * are told apart by the body, not the status.\n */\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_NOT_CLAIMED',\n reason: 'sso_domain_not_claimed',\n message: 'This scope holds no claim on that domain, so there is nothing to revoke.',\n domain,\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REVOKE_DOMAIN, executionContext), { domain, scopeId });\n\n /*\n * ─── Sessions already routed by this domain are NOT terminated, and that is a decision ──\n *\n * \"Revoke the domain\" reads like \"cut the sessions\", and it must not mean that. Domain\n * routing decides where a NEW sign-in is sent; it is not a credential and confers no\n * standing — `DomainOrgLookupResult` says so explicitly, and every reader treats the\n * scope it returns as a hint that may only TIGHTEN an enforcement decision. So a session\n * established while the domain was verified was established by an identity provider that\n * really did authenticate that person; nothing about it becomes false when the routing\n * hint is withdrawn.\n *\n * Ending sessions is a different control with its own doors (member suspension, user\n * deactivation, the session-version fence). Folding it in here would make revocation —\n * the ordinary step in handing a domain to another scope — a mass logout of people whose\n * standing has not changed.\n */\n return { domains: getDomainVerificationService(container).planDomainRevocation(domains, domain) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, utils) => {\n const revoked = takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REVOKE_DOMAIN, executionContext));\n if (!revoked) return updatedRow;\n const { domain, scopeId } = revoked as { domain: string; scopeId: string };\n /*\n * The next scope may skip the wait only once this revoke is durable (#3321). Released any earlier, this scope's own\n * VERIFY still in flight would lose its grace: the next scope takes the row, that VERIFY then wins the row-version pin,\n * and both hold the domain. Past the write it cannot: the row moved, so the pin refuses it.\n */\n const release = () => getDomainVerificationService(container).releaseDomainReservation(variant.scopeType, scopeId, domain);\n const transaction = utils.serviceOptions?.transaction;\n if (transaction) registerTransactionPostCommitEffect(transaction, { key: `sso-domain-release:${variant.scopeType}:${scopeId}:${domain}`, execute: release });\n else await release();\n return { domain, revoked: true };\n },\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// enableDomainSso / disableDomainSso\n// ════════════════════════════════════════════════════════════════════\n\n/**\n * The routing opt-in, both directions. PREFIX like its siblings, so the core UPDATE persists the plan and emits the\n * `RESOURCE_OPERATION_PERFORMED` row a CRITICAL change owes; `authoritativeFields: ['domains']` for the reason the\n * siblings give.\n *\n * ENABLE refuses a domain this scope has not VERIFIED — 409 `SSO_DOMAIN_ROUTING_REQUIRES_VERIFICATION`, the state forbidding the write\n * rather than the caller or the payload. Without it the opt-in would be the #1804 hole by another door: a scope\n * routing a domain it never proved. Exclusivity needs no second check here: a domain is verified by at most ONE scope\n * (`findConflictingScope` and the reservation at verify), so a verified domain cannot be routed by two.\n *\n * DISABLE of a domain that is not routed here is a no-op that answers `ssoEnabled: false`, not a refusal: the state the\n * caller asked for already holds, and an administrator winding single sign-on down must not have to know which\n * domains were on.\n */\nfunction createDomainSsoRoutingFactory(variant: SsoConfigScopeVariant, enabled: boolean): ResourceCustomServiceImplementationFactory {\n const operation = enabled ? SsoConfig_Operations.ENABLE_DOMAIN_SSO : SsoConfig_Operations.DISABLE_DOMAIN_SSO;\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: operation,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.${operation}`,\n // #2297: pure planning over utils.currentObject.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n const service = getDomainVerificationService(container);\n\n if (enabled && !service.canEnableDomainSso(domains, domain)) {\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n // Not `SSO_DOMAIN_NOT_VERIFIED`: that name is the SIGN-IN refusal's message reference (an assertion\n // naming a domain its organization never verified), a different event in a different field.\n code: 'SSO_DOMAIN_ROUTING_REQUIRES_VERIFICATION',\n reason: 'sso_domain_routing_requires_verification',\n message: 'Only a domain this scope has verified can route sign-ins here. Claim it and verify the DNS record first.',\n domain,\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, operation, executionContext), { domain, ssoEnabled: enabled });\n return { domains: service.planDomainSsoRouting(domains, domain, enabled) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, operation, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════\n// repairUnreadableConfiguration (#3345, generalised by #3349)\n// ════════════════════════════════════════════════════\n\n/** What the repair's prefix hands its postfix: the audit row's facts and the reply. */\ninterface ConfigurationRepairBridge {\n readonly scopeId: string;\n readonly ssoConfigId: string;\n readonly repairs: SsoConfigRepair[];\n readonly routingRemoved: string[];\n readonly providersAdmitted: string[];\n readonly remainingFaults: { path: (string | number)[]; message: string }[];\n readonly justification: string;\n readonly repairedByUserId: string;\n}\n\n/**\n * The blocks the repair may write: every block but `emergencyAccess`, which it never changes. Each one re-attached after the\n * strict request DTO strips it, as the domain doors do with `domains`.\n */\nconst REPAIRABLE_BLOCKS: string[] = SSO_CONFIG_BLOCKS.filter((block) => block !== SsoConfigBlock.EMERGENCY_ACCESS);\n\n/**\n * The scope's stored row, read past its DTO (the row is what does not read), by its id and, for an organization, confined\n * to the organization the authorizer admitted the call into. Load-bearing, and measured (#3345): the framework confines\n * an UPDATE's WRITE, so without this a prefix would read and plan another organization's row, and its refusal would hand\n * the caller that organization's paths and domains.\n */\nasync function readConfinedStoredRow(\n variant: SsoConfigScopeVariant,\n container: Container,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n id: string | undefined,\n): Promise<{ stored: Record<string, unknown>; scopeId: string }> {\n const notFound = () => utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'SSO configuration not found.', resourceType: variant.resourceType },\n });\n const admittedOrganizationId = executionContext.organizationId;\n if (variant.scopeType === AuthScopeType.ORGANIZATION && (typeof admittedOrganizationId !== 'string' || admittedOrganizationId.length === 0)) {\n // Fail closed. Measured: on both adapters a filter on an undefined organization matches no row, so the pin passes with\n // or without this. It is kept so the confinement does not depend on how a driver serializes `undefined` (MongoDB's\n // `ignoreUndefined` would turn the filter into `{ _id }`).\n throw notFound();\n }\n const confinement = variant.scopeType === AuthScopeType.ORGANIZATION ? { organizationId: admittedOrganizationId } : {};\n const repositories = container.get<RepositoriesRegistryHandlerBackendService>(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService);\n const [stored] = await repositories.findManyForInfrastructure<Record<string, unknown>>(\n variant.resourceType,\n { ...(id ? { _id: id } : {}), ...confinement },\n undefined,\n { transaction: utils.serviceOptions?.transaction },\n );\n const scopeId = stored?.[variant.scopeField];\n if (!stored || typeof scopeId !== 'string' || scopeId.length === 0) throw notFound();\n return { stored, scopeId };\n}\n\n/** Every social provider the application offers for sign-in: the population a provider restriction can admit. */\nfunction socialLoginProvidersOf(container: Container): string[] {\n if (!container.isBound(SAAS_SERVICE_TYPES.AppConfigService)) return [];\n const appConfig = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n if (!appConfig.isInitialized()) return [];\n return Object.entries(appConfig.config.auth?.socialOAuth2Providers ?? {})\n .filter(([, provider]) => isEnabledSocialOAuth2LoginProvider(provider))\n .map(([providerRef]) => providerRef);\n}\n\n/**\n * The repair from above: a platform super-administrator repairs what makes a scope's configuration fail its schema, each\n * block by its own rule (`planSsoConfigRepair`, which carries the reasoning and what was rejected).\n *\n * - **The stored row, read raw and confined** (`readConfinedStoredRow`).\n * - **A person, signed in.** The audit row and the organization's email name them; a machine credential is refused.\n * - **PREFIX, not OVERRIDE_ALL**, like the five domain doors: the framework's core UPDATE persists the repaired blocks\n * and runs its post-operation lane, so the `RESOURCE_OPERATION_PERFORMED` row and the organization's email follow.\n * - **Recorded once the write commits**: a CRITICAL `SSO_CONFIGURATION_REPAIRED` row with each path and what was done\n * there, the domains whose routing ended, the providers admitted and the justification. A repair that rolls back\n * asserts nothing.\n *\n * The cached copy of this scope's policy is left alone: it is the last copy read whole, which is what enforced while the\n * row could not be read, and the next read of the repaired row replaces it.\n */\nfunction createRepairUnreadableConfigurationFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.repairUnreadableConfiguration`,\n // #2297: the stored row is read with the transaction, planning is pure, and the repair's audit row goes through\n // `emitAuthorityChangeAuditWhenDurable` (a post-commit effect inside a transaction).\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n // The prefix writes the repaired blocks, as the domain doors write `domains`: re-attached after the strict request DTO\n // strips them, so a caller-supplied block is overwritten rather than honoured, on every path, the HTTP one included.\n authoritativeFields: REPAIRABLE_BLOCKS,\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (id, input, executionContext, _operationPath, utils) => {\n if (executionContext.initiatorIds?.machineCredential) {\n throw utils.errorBuilder.buildError(ErrorType.AUTHORIZATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_PRINCIPAL_KIND_NOT_ADMITTED,\n context: { message: 'A scope\\'s single sign-on configuration can only be repaired by a signed-in platform administrator.' },\n });\n }\n const repairedByUserId = executionContext.initiatorIds?.userId;\n if (!repairedByUserId) {\n throw utils.errorBuilder.buildError(ErrorType.AUTHORIZATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_MISSING_INITIATOR,\n context: { message: 'A scope\\'s single sign-on configuration can only be repaired by a signed-in platform administrator.' },\n });\n }\n const request = SsoConfig_RepairUnreadableConfigurationRequestDto.parse(input);\n if (typeof id !== 'string' || id.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n context: { reason: 'sso_config_id_required', message: 'Repairing a configuration requires its id from the route path.' },\n });\n }\n const { stored, scopeId } = await readConfinedStoredRow(variant, container, executionContext, utils, id);\n\n const outcome = planSsoConfigRepair(stored, request, socialLoginProvidersOf(container));\n // `in`, not `repaired`: this package compiles without strictNullChecks, where a boolean discriminant does not narrow.\n if ('refusal' in outcome) {\n // Under keys the error builder admits to a client for VALIDATION and CONFLICT: the operator cannot read the row\n // (it does not read), so the refusal is the only place they learn what to name. Paths and schema messages,\n // domain names and provider refs, never a value.\n throw utils.errorBuilder.buildError(REPAIR_REFUSAL_IS_CONFLICT.has(outcome.refusal) ? ErrorType.CONFLICT : ErrorType.VALIDATION, executionContext, {\n context: {\n code: outcome.refusal,\n message: REPAIR_REFUSAL_MESSAGES[outcome.refusal],\n configurationFaults: outcome.faults.slice(0, 1000).map(({ path, message }) => ({ path, message })),\n ...(outcome.routingRemoved ? { configurationRoutingRemoved: outcome.routingRemoved } : {}),\n ...(outcome.providersAdmitted ? { configurationProvidersAdmitted: outcome.providersAdmitted } : {}),\n ...(outcome.path ? { configurationRepairPath: outcome.path } : {}),\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION, executionContext), {\n scopeId,\n ssoConfigId: id,\n repairs: outcome.repairs,\n routingRemoved: outcome.routingRemoved,\n providersAdmitted: outcome.providersAdmitted,\n remainingFaults: outcome.remainingFaults.map(({ path, message }) => ({ path, message })),\n justification: request.justification,\n repairedByUserId,\n } satisfies ConfigurationRepairBridge as unknown as Record<string, unknown>);\n // assurance-control: WILDO.ACCESS.CROSS_TENANT_ADMINISTRATION — the repair changes only what the schema refuses in one scope's configuration, each block by a rule that lifts no control, recorded with who and why.\n return outcome.blocks as Record<string, unknown>;\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, utils) => {\n const bridge = takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION, executionContext)) as unknown as ConfigurationRepairBridge | undefined;\n if (!bridge || !updatedRow) return updatedRow;\n await emitAuthorityChangeAuditWhenDurable({\n serviceOptions: utils.serviceOptions,\n effectKey: ['sso-configuration-repaired', bridge.ssoConfigId].join(':'),\n logger: utils.logger as LoggerService,\n failureContext: { ssoConfigId: bridge.ssoConfigId, scopeType: variant.scopeType, scopeId: bridge.scopeId },\n emit: async () => {\n const auditLogs = container.isBound(SAAS_SERVICE_TYPES.AuditLogsService) ? container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService) : undefined;\n await auditLogs?.logSsoConfigurationRepaired({\n scopeType: variant.scopeType,\n ...(variant.scopeType === AuthScopeType.ORGANIZATION ? { organizationId: bridge.scopeId } : { applicationId: bridge.scopeId }),\n ssoConfigId: bridge.ssoConfigId,\n repairs: bridge.repairs.map(({ path, action }) => ({ path: JSON.stringify(path), action })),\n routingRemoved: bridge.routingRemoved,\n providersAdmitted: bridge.providersAdmitted,\n repairedByUserId: bridge.repairedByUserId,\n justification: bridge.justification,\n }, executionContext);\n },\n });\n return {\n repairs: bridge.repairs,\n routingRemoved: bridge.routingRemoved,\n providersAdmitted: bridge.providersAdmitted,\n remainingFaults: bridge.remainingFaults,\n };\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/** The refusals that are about the row's STATE rather than the request's shape: 409, as the floors answer. */\nconst REPAIR_REFUSAL_IS_CONFLICT: ReadonlySet<SsoConfigRepairRefusal> = new Set([\n SsoConfigRepairRefusal.CONFIGURATION_READABLE,\n SsoConfigRepairRefusal.ROUTING_REMOVED_UNACKNOWLEDGED,\n SsoConfigRepairRefusal.PROVIDERS_ADMITTED_UNACKNOWLEDGED,\n SsoConfigRepairRefusal.EMERGENCY_ACCESS_NOT_REPAIRABLE,\n]);\n\n/** What each refusal tells the operator to do next. */\nconst REPAIR_REFUSAL_MESSAGES: Readonly<Record<SsoConfigRepairRefusal, string>> = {\n [SsoConfigRepairRefusal.CONFIGURATION_READABLE]:\n 'This scope\\'s single sign-on configuration reads, so there is nothing to repair here: its administrators change it through its own doors.',\n [SsoConfigRepairRefusal.PATH_NOT_FOUND]: 'A path named for repair is not in the stored configuration. The places the schema refuses are listed in `configurationFaults`.',\n [SsoConfigRepairRefusal.PATH_NOT_AT_FAULT]:\n 'A path named for repair is not one of the places the schema refuses, or inside one, so repairing it would change a part that reads. Only what is listed in `configurationFaults` may be repaired.',\n [SsoConfigRepairRefusal.PATHS_OVERLAP]: 'Two paths named for repair are the same, or one lies inside the other. Name each place once.',\n [SsoConfigRepairRefusal.STILL_UNREADABLE]: 'A block this repair touches would still not read. What remains is listed in `configurationFaults`.',\n [SsoConfigRepairRefusal.ROUTING_REMOVED_UNACKNOWLEDGED]:\n 'This repair stops routing the domains in `configurationRoutingRemoved` to this scope\\'s identity provider. Name each of them in `acknowledgedRoutingRemoved` to proceed.',\n [SsoConfigRepairRefusal.PROVIDERS_ADMITTED_UNACKNOWLEDGED]:\n 'This repair lets this scope\\'s members use the social providers in `configurationProvidersAdmitted`, which the stored restrictions refused. Name each of them in `acknowledgedProvidersAdmitted` to proceed.',\n [SsoConfigRepairRefusal.EMERGENCY_ACCESS_NOT_REPAIRABLE]:\n 'The break-glass block is never changed by this door: removing an entry takes a way in away and adding one grants it. Restore the stored row out of band, and record why.',\n [SsoConfigRepairRefusal.OVERRIDE_NOT_REMOVABLE]:\n 'A social credential override that reads and has no duplicate is never removed: it holds the scope\\'s own sealed credentials. Name a duplicate, or an entry listed in `configurationFaults`.',\n};\n\n// ════════════════════════════════════════════════════\n// describeUnreadableFields (#3349)\n// ════════════════════════════════════════════════════\n\n/**\n * What of the scope's configuration does not read, for its own administrators: paths and the schema's messages, never a\n * value. REPLACE: the core READ fails on exactly the row this answers about (#3344). Read raw and confined to the scope,\n * as the repair reads it. An empty list for a row that reads.\n */\nfunction createDescribeUnreadableFieldsFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.DESCRIBE_UNREADABLE_FIELDS,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.describeUnreadableFields`,\n handlers: {\n replaceCoreOperations: async (id, _input, executionContext, _operationPath, utils) => {\n const { stored } = await readConfinedStoredRow(variant, container, executionContext, utils, typeof id === 'string' && id.length > 0 ? id : undefined);\n return { unreadableFields: ssoConfigBlockFaults(stored).map(({ block, path, message }) => ({ block, path, message })) };\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\nexport function createSsoConfigDomainVerificationFactories(): ResourceCustomServiceImplementationFactory[] {\n return SSO_CONFIG_SCOPE_VARIANTS.flatMap((variant) => [\n createClaimDomainFactory(variant),\n createVerifyDomainFactory(variant),\n createRevokeDomainFactory(variant),\n createDomainSsoRoutingFactory(variant, true),\n createDomainSsoRoutingFactory(variant, false),\n createRepairUnreadableConfigurationFactory(variant),\n ]);\n}\n\n/**\n * The administrator's read of what does not read (#3349), at both scopes. Its own export, beside the writing verbs above\n * rather than among them: it writes nothing, so the version pin every one of them carries (#3279) has nothing to pin.\n */\nexport function createSsoConfigUnreadableFieldsFactories(): ResourceCustomServiceImplementationFactory[] {\n return SSO_CONFIG_SCOPE_VARIANTS.map((variant) => createDescribeUnreadableFieldsFactory(variant));\n}\n"]}
1
+ {"version":3,"file":"sso-config-domain-verification.custom-impl.backend.service.js","sourceRoot":"","sources":["../../../../../../src/security/authentications/services/custom-impls/sso-config-domain-verification.custom-impl.backend.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * SSO Config — domain-ownership and sign-in routing operations (#424, #2519)\n *\n * Five public operations that turn enterprise domain routing from an out-of-band database write\n * into a self-service admin flow; one platform operator's repair (`repairUnreadableConfiguration`, #3345, #3349) for a\n * scope whose configuration no longer reads, and the administrator's list of what does not read (`describeUnreadableFields`):\n *\n * claimDomain → mints a DNS-TXT challenge, records the domain as `pending`, returns the record\n * verifyDomain → resolves the record, records `verified` or `failed`\n * revokeDomain → removes the claim, its status, its nonce and its `ssoEnabledDomains` entry\n * enableDomainSso → opts a VERIFIED domain into sign-in routing (`ssoEnabledDomains`)\n * disableDomainSso → withdraws that opt-in, keeping the proof\n *\n * The last two exist because #1226 made routing need BOTH proof and the scope's opt-in, and #1804 then\n * let `domains` move only through the first three — which write the proof alone. Until #2519 no\n * organization could turn single sign-on on for its own domain without a database write.\n *\n * ## Why PREFIX, and not OVERRIDE_ALL\n *\n * Each handler computes the new `domains` block and returns it; the framework's own core UPDATE\n * persists it. `OVERRIDE_ALL` returns before the post-operation lane, so it emits NO\n * `RESOURCE_OPERATION_PERFORMED` audit event — and the audit row is the control that makes a\n * privileged configuration change with cross-tenant reach accountable. An operation that granted a\n * tenant SSO routing authority and left no trail would be strictly worse than the database write it\n * replaces, which at least happens where a DBA can see it.\n *\n * ## Where the domain-ownership rules live\n *\n * In `DomainVerificationBackendService`, as pure planners. This file is the door: it resolves the\n * scope, enforces the refusals, and hands the plan to the framework. Nothing here re-implements\n * what a claim or a revocation means.\n */\n\nimport {\n AuthScopeType,\n CoreResourceType,\n DomainVerificationStatus,\n ErrorCustomMessageReference,\n ErrorType,\n ResourceOperationVariantType,\n SsoConfig_Operations,\n SsoConfig_RepairUnreadableConfigurationRequestDto,\n SsoConfigRepairRefusal,\n SSO_CONFIG_BLOCKS,\n SsoConfigBlock,\n ssoConfigBlockFaults,\n} from '@wildo-ai/saas-models';\nimport type { SsoConfigBase } from '@wildo-ai/saas-models';\nimport type { Container } from 'inversify';\nimport { SAAS_SERVICE_TYPES } from '~wildo-backend-lib/inject/models/service-types';\nimport {\n createResourceCustomServiceImplementation,\n ResourceCustomServiceImplementationHookTransactionPosture,\n type ResourceCustomServiceImplementationFactory,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation.factory.backend';\nimport type { ResourcesRegistryBackendService } from '~wildo-backend-lib/resources/services/resources-registry.backend.service';\nimport type {\n DomainVerificationBackendService,\n SsoConfigDomains,\n} from '~wildo-backend-lib/security/authentications/services/admin-config/domain-verification.backend.service';\nimport {\n ResourceOperationBeforeTransactionalCoreDisposition,\n type ResourceOperation_CustomImplementation_Utils,\n} from '~wildo-backend-lib/base-classes/services/services/resource-operation-custom-implementation-base.backend.service';\nimport type { ExecutionContext } from '~wildo-backend-lib/runtime/models/execution-context.backend.schemas';\nimport { registerTransactionPostCommitEffect } from '~wildo-backend-lib/databases/models/transaction.shared.schemas';\nimport { DnsLookupUnavailableError } from '~wildo-backend-lib/security/dns/dns-txt-lookup.backend.service';\nimport type { RepositoriesRegistryHandlerBackendService } from '~wildo-backend-lib/base-classes/services/repositories/repositories-registry-handler.backend.service';\nimport type { AuditLogsBackendService } from '~wildo-backend-lib/compliance/audit-trails/services/audit-logs.backend.service';\nimport type { LoggerService } from '~wildo-backend-lib/monitoring/logger/services/logger.service';\nimport { emitAuthorityChangeAuditWhenDurable } from '~wildo-backend-lib/organizations/services/authority-change-audit.backend.utils';\nimport { planSsoConfigRepair, type SsoConfigRepair } from '~wildo-backend-lib/security/authentications/services/admin-config/sso-config-repair.backend.utils';\nimport type { AppConfigurationService } from '~wildo-backend-lib/config/services/app-configuration.backend.service';\nimport { isEnabledSocialOAuth2LoginProvider } from '~wildo-backend-lib/security/authentications/utils/social-oauth2-purpose.backend.utils';\n\n// ── The two scope variants, and how each names its scope ─────────────\n\ninterface SsoConfigScopeVariant {\n readonly resourceType: CoreResourceType;\n readonly scopeType: AuthScopeType;\n readonly scopeField: 'organizationId' | 'applicationId';\n}\n\nconst SSO_CONFIG_SCOPE_VARIANTS: readonly SsoConfigScopeVariant[] = [\n {\n resourceType: CoreResourceType.ORGANIZATION_SSO_CONFIG,\n scopeType: AuthScopeType.ORGANIZATION,\n scopeField: 'organizationId',\n },\n {\n resourceType: CoreResourceType.APPLICATION_SSO_CONFIG,\n scopeType: AuthScopeType.APPLICATION,\n scopeField: 'applicationId',\n },\n];\n\n/**\n * Carries the two values a response needs that the persisted row does not hold, from the PREFIX\n * that computed them to the POSTFIX that shapes the reply.\n *\n * Bounded on purpose. The precedent bridges in this tree (`ROTATE_BRIDGE_BY_TARGET_ID`) delete\n * their entry in the postfix and rely on the postfix always running; a core UPDATE that throws\n * between the two leaks one entry forever. Expiring on write costs one `Date.now()` per call and\n * removes the question.\n */\nconst RESPONSE_BRIDGE_TTL_MS = 60_000;\nconst RESPONSE_BRIDGE = new Map<string, { value: Record<string, unknown>; expiresAt: number }>();\n\n/**\n * Keyed on the REQUEST, not on the row.\n *\n * The postfix receives the persisted row and the execution context — never the request body — so it\n * cannot re-derive which domain the call was about. `correlationId` is minted per request and is\n * the same value in both handlers, which makes the hand-off exact: two admins claiming two domains\n * on the same configuration row at the same instant cannot read each other's response.\n */\nfunction bridgeKey(resourceType: CoreResourceType, operation: string, executionContext: ExecutionContext<any>): string {\n return `${resourceType}|${operation}|${executionContext.correlationId}`;\n}\n\nfunction putBridged(key: string, value: Record<string, unknown>): void {\n const now = Date.now();\n for (const [existingKey, entry] of RESPONSE_BRIDGE) {\n if (entry.expiresAt <= now) RESPONSE_BRIDGE.delete(existingKey);\n }\n RESPONSE_BRIDGE.set(key, { value, expiresAt: now + RESPONSE_BRIDGE_TTL_MS });\n}\n\nfunction takeBridged(key: string): Record<string, unknown> | undefined {\n const entry = RESPONSE_BRIDGE.get(key);\n RESPONSE_BRIDGE.delete(key);\n if (!entry || entry.expiresAt <= Date.now()) return undefined;\n return entry.value;\n}\n\n// ── Shared request resolution ────────────────────────────────────────\n\ninterface ResolvedDomainRequest {\n readonly domain: string;\n readonly scopeId: string;\n readonly domains: SsoConfigDomains;\n}\n\n/**\n * The row being updated, its scope id, and the normalised domain.\n *\n * `utils.currentObject` is the pre-image the framework already fetched for this UPDATE, so nothing\n * here re-reads the config. The domain is lowercased HERE, once, because every stored map is keyed\n * on the lowercase form and a second normalisation site is a second place for the two to disagree.\n */\nfunction resolveDomainRequest(\n variant: SsoConfigScopeVariant,\n input: unknown,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): ResolvedDomainRequest {\n const rawDomain = (input as { domain?: unknown } | undefined)?.domain;\n if (typeof rawDomain !== 'string' || rawDomain.trim().length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n context: {\n code: 'SSO_DOMAIN_REQUIRED',\n reason: 'sso_domain_required',\n message: 'Provide `domain`: the DNS hostname this scope is claiming.',\n },\n });\n }\n\n const currentObject = utils.currentObject as (SsoConfigBase & Record<string, unknown>) | undefined;\n const scopeId = currentObject?.[variant.scopeField];\n if (!currentObject?.domains || typeof scopeId !== 'string' || scopeId.length === 0) {\n // The row is addressed by its scope (a one-to-one composition), so a missing scope id means the\n // framework could not resolve the singleton — never that the caller addressed someone else.\n throw utils.errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {\n context: {\n code: 'SSO_CONFIG_SCOPE_UNRESOLVED',\n reason: 'sso_config_scope_unresolved',\n message: 'The SSO configuration row for this scope could not be resolved.',\n resourceType: variant.resourceType,\n },\n });\n }\n\n return { domain: rawDomain.trim().toLowerCase(), scopeId, domains: currentObject.domains };\n}\n\nfunction getDomainVerificationService(container: Container): DomainVerificationBackendService {\n return container.get<DomainVerificationBackendService>(SAAS_SERVICE_TYPES.DomainVerificationService);\n}\n\n/**\n * Refuse when another scope already holds this domain VERIFIED.\n *\n * Run at CLAIM as a helpful early refusal, and again at VERIFY because that is the gate that\n * matters: a claim is not a lock, so another scope can complete its own verification in between.\n * Two scopes verifying at the same moment both still pass this read, which is why a proven domain is then reserved (#3321).\n *\n * **The holder is deliberately not named.** Telling one tenant which other tenant holds a domain\n * discloses a customer's configuration to a stranger who supplied nothing but a hostname. The\n * message says what to do instead — the current holder revokes, and then the claim succeeds — which\n * is the only remedy anyway.\n */\nasync function assertDomainNotHeldElsewhere(\n container: Container,\n variant: SsoConfigScopeVariant,\n scopeId: string,\n domain: string,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): Promise<void> {\n const conflict = await getDomainVerificationService(container)\n .findConflictingScope(variant.scopeType, scopeId, domain);\n if (conflict) throw domainHeldElsewhere(domain, executionContext, utils);\n}\n\n/** The refusal a domain another scope holds answers, from the read above or from the store's reservation (#3321). */\nfunction domainHeldElsewhere(domain: string, executionContext: ExecutionContext<any>, utils: ResourceOperation_CustomImplementation_Utils) {\n return utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_VERIFIED_ELSEWHERE',\n reason: 'sso_domain_verified_elsewhere',\n message:\n 'Another scope holds this domain, verified or being verified. A domain routes sign-ins to exactly one '\n + 'identity provider, so it must be revoked where it is held before it can be claimed here.',\n domain,\n },\n });\n}\n\n// ════════════════════════════════════════════════════════════════════\n// claimDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createClaimDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.CLAIM_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.claimDomain`,\n // #2297: the exclusivity check is a read of OTHER scopes' committed configs (a plain read, which the row lock does not\n // block); planning the claim is pure. Nothing leaves the database.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n await assertDomainNotHeldElsewhere(container, variant, scopeId, domain, executionContext, utils);\n\n const plan = getDomainVerificationService(container).planDomainClaim(domains, domain);\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.CLAIM_DOMAIN, executionContext), {\n domain,\n status: DomainVerificationStatus.PENDING,\n dnsName: plan.dnsName,\n dnsRecordValue: plan.dnsRecordValue,\n });\n\n // The ONLY key returned. The core UPDATE `$set`s what it is given, so returning the whole\n // row here would re-write every other block from a pre-image this handler never validated.\n return { domains: plan.domains };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.CLAIM_DOMAIN, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// verifyDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createVerifyDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.VERIFY_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.verifyDomain`,\n /*\n * #2297: split so the write keeps its audit row through a crash. Two effects feed the write and must stay OUTSIDE the\n * transaction: the DNS lookup (up to ~10 s, which would hold the row lock, and a retried attempt would ask again and\n * could read another answer) and the domain reservation, which must AUTOCOMMIT (a unique violation aborts a PostgreSQL\n * transaction, so the loser could not answer its refusal from inside one; `DomainVerificationBackendService.reserveDomain`).\n * - `beforeTransactionalCore` (outside, once, before the transaction): the challenge check, the exclusivity read, the\n * DNS lookup and the reservation, in that order, exactly as the prefix used to run them. Its answer (the challenge\n * it checked and what DNS said) rides to the core as the phase's frozen continuation.\n * - PREFIX (inside, retried with the attempt): re-reads the row the attempt holds and applies that answer, but only\n * while the row still holds the SAME challenge: a re-claim committed in between replaced the nonce, and an answer\n * about the old one says nothing about the new one, so the attempt refuses rather than verify against it.\n * Nothing else leaves the database, so the transaction is the framework's and the row is kept with its commit.\n */\n transactionalCore: true,\n transactionParticipants: {},\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n beforeTransactionalCore: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n const service = getDomainVerificationService(container);\n const expectedToken = requireVerificationChallenge(service, domains, domain, executionContext, utils);\n\n // Re-checked HERE, not only at claim: a claim takes no lock, so another scope may have\n // completed its own verification since. This is the write that confers routing authority\n // and therefore the one that must be exclusive.\n await assertDomainNotHeldElsewhere(container, variant, scopeId, domain, executionContext, utils);\n\n let challenge: { verified: boolean; recordsFound: string[] };\n try {\n challenge = await service.checkDomainChallenge(domain, expectedToken);\n } catch (error) {\n if (error instanceof DnsLookupUnavailableError) {\n // DNS could not be ASKED. That is not a failed check: recording `failed` would tell the\n // administrator their correct record is missing — and on a re-verify would withdraw\n // routing from a domain that is still theirs. Refuse, persist nothing, and say so. The\n // email lane answers its own DNS outage the same way (`EMAIL_DOMAIN_DNS_UNAVAILABLE`).\n throw utils.errorBuilder.buildError(ErrorType.EXTERNAL_SERVICE, executionContext, {\n context: {\n code: 'SSO_DOMAIN_DNS_UNAVAILABLE',\n reason: 'sso_domain_dns_unavailable',\n message: `DNS could not be asked for ${service.verificationDnsName(domain)}. Nothing was changed; try again.`,\n domain,\n },\n });\n }\n throw error;\n }\n const { verified, recordsFound } = challenge;\n // This read and the one above cannot see a verification running beside them; the reservation's unique row can (#3321).\n if (verified && await service.reserveDomain(variant.scopeType, scopeId, domain)) {\n throw domainHeldElsewhere(domain, executionContext, utils);\n }\n return {\n disposition: ResourceOperationBeforeTransactionalCoreDisposition.CONTINUE,\n coreInputPatch: {},\n continuation: { domain, checkedToken: expectedToken, verified, recordsFound } satisfies VerifyDomainContinuation,\n };\n },\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n const service = getDomainVerificationService(container);\n const checked = utils.beforeTransactionalCore?.continuation as VerifyDomainContinuation | undefined;\n if (!checked || checked.domain !== domain) {\n throw utils.errorBuilder.buildError(ErrorType.INTERNAL, executionContext, {\n context: { reason: 'sso_domain_verification_unchecked', message: 'The domain challenge was not checked before the write.', domain },\n });\n }\n // The challenge the DNS answer is about must still be the row's: a claim committed since the check replaced it.\n if (requireVerificationChallenge(service, domains, domain, executionContext, utils) !== checked.checkedToken) {\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_CHALLENGE_CHANGED',\n reason: 'sso_domain_challenge_changed',\n message: 'This domain was claimed again while it was being verified, so its challenge changed. Verify it again.',\n domain,\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.VERIFY_DOMAIN, executionContext), {\n domain,\n status: checked.verified ? DomainVerificationStatus.VERIFIED : DomainVerificationStatus.FAILED,\n dnsName: service.verificationDnsName(domain),\n dnsRecordsFound: checked.recordsFound,\n });\n\n return { domains: service.planVerificationOutcome(domains, domain, checked.verified) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.VERIFY_DOMAIN, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/** What `verifyDomain`'s `beforeTransactionalCore` learned, outside the transaction (#2297). */\ninterface VerifyDomainContinuation {\n readonly domain: string;\n /** The challenge DNS was asked about: the core applies the answer only while the row still holds it. */\n readonly checkedToken: string;\n readonly verified: boolean;\n readonly recordsFound: string[];\n}\n\n/**\n * The verification challenge the row holds for `domain`, or a refusal. A claim mints the nonce, so verifying without one is\n * not a failed check — it is a request for a challenge that was never raised. Saying so is what stops an operator publishing\n * a record and waiting for a verification that can never pass.\n */\nfunction requireVerificationChallenge(\n service: DomainVerificationBackendService,\n domains: SsoConfigDomains,\n domain: string,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n): string {\n const expectedToken = service.getVerificationToken(domains, domain);\n if (!expectedToken) {\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_NOT_CLAIMED',\n reason: 'sso_domain_not_claimed',\n message: 'No verification challenge exists for this domain in this scope. Claim it first.',\n domain,\n },\n });\n }\n return expectedToken;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// revokeDomain\n// ════════════════════════════════════════════════════════════════════\n\nfunction createRevokeDomainFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.REVOKE_DOMAIN,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.revokeDomain`,\n // #2297: the prefix is pure, and the reservation's release is registered as a post-commit effect inside a transaction.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n /**\n * The prefix WRITES `domains`, and nothing else can.\n *\n * Without this the repository's strict re-parse drops the key the hook just computed and the\n * operation answers 200 having persisted nothing — the silent no-op the sibling lifecycle verbs\n * (`organizations.requestDeletion`, `organizationMembers.grantOwnership`) each declare against.\n * Declaring it also settles the contract in the other direction: a caller-supplied `domains` is\n * OVERWRITTEN by the hook's value rather than honoured, so the only way to move this block\n * remains the five operations that own it (claim, verify and revoke, and the routing opt-in and\n * opt-out).\n */\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, scopeId, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n\n const isClaimed = domains.verifiedDomains.includes(domain)\n || domains.domainVerificationStatus?.[domain] !== undefined\n || domains.ssoEnabledDomains.includes(domain);\n if (!isClaimed) {\n /**\n * CONFLICT, not NOT_FOUND — corrected 2026-09-10 after the refusal was driven over HTTP\n * for the first time, and for three independent reasons.\n *\n * **It could not name itself.** `sanitizeErrorForClient` allow-lists a refusal's\n * `context` — and with it the client-branchable `code` — only for VALIDATION, CONFLICT\n * and RATE_LIMIT; every other type has its context stripped whole. So as a NOT_FOUND\n * this answered a bare `not_found` and `SSO_DOMAIN_NOT_CLAIMED` reached no client. A\n * status and a name that cannot both be delivered is not a contract.\n *\n * **Its SIBLING already answers 409 for the same condition.** `verifyDomain` refuses a\n * domain with no challenge as a CONFLICT, eight hundred lines up in this same file. One\n * condition, two verbs, two answers — the shape\n * `.claude/rules/invariant-call-site-enumeration.md` exists for.\n *\n * **And 409 is what the framework's own rule asks for here.**\n * `administrative-continuity-floors.md`: refuse with CONFLICT, never 403 or 400, when\n * the caller IS authorized and the payload IS valid and what forbids the write is the\n * current STATE. The addressed row — the SSO config singleton — exists and resolved;\n * what does not exist is a claim inside it. A 404 on a URL that resolved is also the\n * exact ambiguity issue #542 records against itself: a dispatched 404 and a routing 404\n * are told apart by the body, not the status.\n */\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n code: 'SSO_DOMAIN_NOT_CLAIMED',\n reason: 'sso_domain_not_claimed',\n message: 'This scope holds no claim on that domain, so there is nothing to revoke.',\n domain,\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REVOKE_DOMAIN, executionContext), { domain, scopeId });\n\n /*\n * ─── Sessions already routed by this domain are NOT terminated, and that is a decision ──\n *\n * \"Revoke the domain\" reads like \"cut the sessions\", and it must not mean that. Domain\n * routing decides where a NEW sign-in is sent; it is not a credential and confers no\n * standing — `DomainOrgLookupResult` says so explicitly, and every reader treats the\n * scope it returns as a hint that may only TIGHTEN an enforcement decision. So a session\n * established while the domain was verified was established by an identity provider that\n * really did authenticate that person; nothing about it becomes false when the routing\n * hint is withdrawn.\n *\n * Ending sessions is a different control with its own doors (member suspension, user\n * deactivation, the session-version fence). Folding it in here would make revocation —\n * the ordinary step in handing a domain to another scope — a mass logout of people whose\n * standing has not changed.\n */\n return { domains: getDomainVerificationService(container).planDomainRevocation(domains, domain) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, utils) => {\n const revoked = takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REVOKE_DOMAIN, executionContext));\n if (!revoked) return updatedRow;\n const { domain, scopeId } = revoked as { domain: string; scopeId: string };\n /*\n * The next scope may skip the wait only once this revoke is durable (#3321). Released any earlier, this scope's own\n * VERIFY still in flight would lose its grace: the next scope takes the row, that VERIFY then wins the row-version pin,\n * and both hold the domain. Past the write it cannot: the row moved, so the pin refuses it.\n */\n const release = () => getDomainVerificationService(container).releaseDomainReservation(variant.scopeType, scopeId, domain);\n const transaction = utils.serviceOptions?.transaction;\n if (transaction) registerTransactionPostCommitEffect(transaction, { key: `sso-domain-release:${variant.scopeType}:${scopeId}:${domain}`, execute: release });\n else await release();\n return { domain, revoked: true };\n },\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════════════════════\n// enableDomainSso / disableDomainSso\n// ════════════════════════════════════════════════════════════════════\n\n/**\n * The routing opt-in, both directions. PREFIX like its siblings, so the core UPDATE persists the plan and emits the\n * `RESOURCE_OPERATION_PERFORMED` row a CRITICAL change owes; `authoritativeFields: ['domains']` for the reason the\n * siblings give.\n *\n * ENABLE refuses a domain this scope has not VERIFIED — 409 `SSO_DOMAIN_ROUTING_REQUIRES_VERIFICATION`, the state forbidding the write\n * rather than the caller or the payload. Without it the opt-in would be the #1804 hole by another door: a scope\n * routing a domain it never proved. Exclusivity needs no second check here: a domain is verified by at most ONE scope\n * (`findConflictingScope` and the reservation at verify), so a verified domain cannot be routed by two.\n *\n * DISABLE of a domain that is not routed here is a no-op that answers `ssoEnabled: false`, not a refusal: the state the\n * caller asked for already holds, and an administrator winding single sign-on down must not have to know which\n * domains were on.\n */\nfunction createDomainSsoRoutingFactory(variant: SsoConfigScopeVariant, enabled: boolean): ResourceCustomServiceImplementationFactory {\n const operation = enabled ? SsoConfig_Operations.ENABLE_DOMAIN_SSO : SsoConfig_Operations.DISABLE_DOMAIN_SSO;\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: operation,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.${operation}`,\n // #2297: pure planning over utils.currentObject.\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n authoritativeFields: ['domains'],\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (_id, input, executionContext, _operationPath, utils) => {\n const { domain, domains } = resolveDomainRequest(variant, input, executionContext, utils);\n const service = getDomainVerificationService(container);\n\n if (enabled && !service.canEnableDomainSso(domains, domain)) {\n throw utils.errorBuilder.buildError(ErrorType.CONFLICT, executionContext, {\n context: {\n // Not `SSO_DOMAIN_NOT_VERIFIED`: that name is the SIGN-IN refusal's message reference (an assertion\n // naming a domain its organization never verified), a different event in a different field.\n code: 'SSO_DOMAIN_ROUTING_REQUIRES_VERIFICATION',\n reason: 'sso_domain_routing_requires_verification',\n message: 'Only a domain this scope has verified can route sign-ins here. Claim it and verify the DNS record first.',\n domain,\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, operation, executionContext), { domain, ssoEnabled: enabled });\n return { domains: service.planDomainSsoRouting(domains, domain, enabled) };\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, _utils) =>\n takeBridged(bridgeKey(variant.resourceType, operation, executionContext)) ?? updatedRow,\n },\n });\n\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n// ════════════════════════════════════════════════════\n// repairUnreadableConfiguration (#3345, generalised by #3349)\n// ════════════════════════════════════════════════════\n\n/** What the repair's prefix hands its postfix: the audit row's facts and the reply. */\ninterface ConfigurationRepairBridge {\n readonly scopeId: string;\n readonly ssoConfigId: string;\n readonly repairs: SsoConfigRepair[];\n readonly routingRemoved: string[];\n readonly providersAdmitted: string[];\n readonly remainingFaults: { path: (string | number)[]; message: string }[];\n readonly justification: string;\n readonly repairedByUserId: string;\n}\n\n/**\n * The blocks the repair may write: every block but `emergencyAccess`, which it never changes. Each one re-attached after the\n * strict request DTO strips it, as the domain doors do with `domains`.\n */\nconst REPAIRABLE_BLOCKS: string[] = SSO_CONFIG_BLOCKS.filter((block) => block !== SsoConfigBlock.EMERGENCY_ACCESS);\n\n/**\n * The scope's stored row, read past its DTO (the row is what does not read), by its id and, for an organization, confined\n * to the organization the authorizer admitted the call into. Load-bearing, and measured (#3345): the framework confines\n * an UPDATE's WRITE, so without this a prefix would read and plan another organization's row, and its refusal would hand\n * the caller that organization's paths and domains.\n */\nasync function readConfinedStoredRow(\n variant: SsoConfigScopeVariant,\n container: Container,\n executionContext: ExecutionContext<any>,\n utils: ResourceOperation_CustomImplementation_Utils,\n id: string | undefined,\n): Promise<{ stored: Record<string, unknown>; scopeId: string }> {\n const notFound = () => utils.errorBuilder.buildError(ErrorType.NOT_FOUND, executionContext, {\n customMessageReference: ErrorCustomMessageReference.NOT_FOUND,\n context: { message: 'SSO configuration not found.', resourceType: variant.resourceType },\n });\n const admittedOrganizationId = executionContext.organizationId;\n if (variant.scopeType === AuthScopeType.ORGANIZATION && (typeof admittedOrganizationId !== 'string' || admittedOrganizationId.length === 0)) {\n // Fail closed. Measured: on both adapters a filter on an undefined organization matches no row, so the pin passes with\n // or without this. It is kept so the confinement does not depend on how a driver serializes `undefined` (MongoDB's\n // `ignoreUndefined` would turn the filter into `{ _id }`).\n throw notFound();\n }\n const confinement = variant.scopeType === AuthScopeType.ORGANIZATION ? { organizationId: admittedOrganizationId } : {};\n const repositories = container.get<RepositoriesRegistryHandlerBackendService>(SAAS_SERVICE_TYPES.RepositoriesRegistryHandlerService);\n const [stored] = await repositories.findManyForInfrastructure<Record<string, unknown>>(\n variant.resourceType,\n { ...(id ? { _id: id } : {}), ...confinement },\n undefined,\n { transaction: utils.serviceOptions?.transaction },\n );\n const scopeId = stored?.[variant.scopeField];\n if (!stored || typeof scopeId !== 'string' || scopeId.length === 0) throw notFound();\n return { stored, scopeId };\n}\n\n/** Every social provider the application offers for sign-in: the population a provider restriction can admit. */\nfunction socialLoginProvidersOf(container: Container): string[] {\n if (!container.isBound(SAAS_SERVICE_TYPES.AppConfigService)) return [];\n const appConfig = container.get<AppConfigurationService>(SAAS_SERVICE_TYPES.AppConfigService);\n if (!appConfig.isInitialized()) return [];\n return Object.entries(appConfig.config.auth?.socialOAuth2Providers ?? {})\n .filter(([, provider]) => isEnabledSocialOAuth2LoginProvider(provider))\n .map(([providerRef]) => providerRef);\n}\n\n/**\n * The repair from above: a platform super-administrator repairs what makes a scope's configuration fail its schema, each\n * block by its own rule (`planSsoConfigRepair`, which carries the reasoning and what was rejected).\n *\n * - **The stored row, read raw and confined** (`readConfinedStoredRow`).\n * - **A person, signed in.** The audit row and the organization's email name them; a machine credential is refused.\n * - **PREFIX, not OVERRIDE_ALL**, like the five domain doors: the framework's core UPDATE persists the repaired blocks\n * and runs its post-operation lane, so the `RESOURCE_OPERATION_PERFORMED` row and the organization's email follow.\n * - **Recorded once the write commits**: a CRITICAL `SSO_CONFIGURATION_REPAIRED` row with each path and what was done\n * there, the domains whose routing ended, the providers admitted and the justification. A repair that rolls back\n * asserts nothing.\n *\n * The cached copy of this scope's policy is left alone: it is the last copy read whole, which is what enforced while the\n * row could not be read, and the next read of the repaired row replaces it.\n */\nfunction createRepairUnreadableConfigurationFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.repairUnreadableConfiguration`,\n // #2297: the stored row is read with the transaction, planning is pure, and the repair's audit row goes through\n // `emitAuthorityChangeAuditWhenDurable` (a post-commit effect inside a transaction).\n hookTransactionPosture: ResourceCustomServiceImplementationHookTransactionPosture.RUNS_INSIDE_TRANSACTION,\n // The prefix writes the repaired blocks, as the domain doors write `domains`: re-attached after the strict request DTO\n // strips them, so a caller-supplied block is overwritten rather than honoured, on every path, the HTTP one included.\n authoritativeFields: REPAIRABLE_BLOCKS,\n coreWritePinsRowVersion: true,\n handlers: {\n prefixCoreOperations: async (id, input, executionContext, _operationPath, utils) => {\n if (executionContext.initiatorIds?.machineCredential) {\n throw utils.errorBuilder.buildError(ErrorType.AUTHORIZATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_PRINCIPAL_KIND_NOT_ADMITTED,\n context: { message: 'A scope\\'s single sign-on configuration can only be repaired by a signed-in platform administrator.' },\n });\n }\n const repairedByUserId = executionContext.initiatorIds?.userId;\n if (!repairedByUserId) {\n throw utils.errorBuilder.buildError(ErrorType.AUTHORIZATION, executionContext, {\n customMessageReference: ErrorCustomMessageReference.AUTHORIZATIONS_MISSING_INITIATOR,\n context: { message: 'A scope\\'s single sign-on configuration can only be repaired by a signed-in platform administrator.' },\n });\n }\n const request = SsoConfig_RepairUnreadableConfigurationRequestDto.parse(input);\n if (typeof id !== 'string' || id.length === 0) {\n throw utils.errorBuilder.buildError(ErrorType.VALIDATION, executionContext, {\n context: { reason: 'sso_config_id_required', message: 'Repairing a configuration requires its id from the route path.' },\n });\n }\n const { stored, scopeId } = await readConfinedStoredRow(variant, container, executionContext, utils, id);\n\n const outcome = planSsoConfigRepair(stored, request, socialLoginProvidersOf(container));\n // `in`, not `repaired`: this package compiles without strictNullChecks, where a boolean discriminant does not narrow.\n if ('refusal' in outcome) {\n // Under keys the error builder admits to a client for VALIDATION and CONFLICT: the operator cannot read the row\n // (it does not read), so the refusal is the only place they learn what to name. Paths and schema messages,\n // domain names and provider refs, never a value.\n throw utils.errorBuilder.buildError(REPAIR_REFUSAL_IS_CONFLICT.has(outcome.refusal) ? ErrorType.CONFLICT : ErrorType.VALIDATION, executionContext, {\n context: {\n code: outcome.refusal,\n message: REPAIR_REFUSAL_MESSAGES[outcome.refusal],\n configurationFaults: outcome.faults.slice(0, 1000).map(({ path, message }) => ({ path, message })),\n ...(outcome.routingRemoved ? { configurationRoutingRemoved: outcome.routingRemoved } : {}),\n ...(outcome.providersAdmitted ? { configurationProvidersAdmitted: outcome.providersAdmitted } : {}),\n ...(outcome.path ? { configurationRepairPath: outcome.path } : {}),\n },\n });\n }\n\n putBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION, executionContext), {\n scopeId,\n ssoConfigId: id,\n repairs: outcome.repairs,\n routingRemoved: outcome.routingRemoved,\n providersAdmitted: outcome.providersAdmitted,\n remainingFaults: outcome.remainingFaults.map(({ path, message }) => ({ path, message })),\n justification: request.justification,\n repairedByUserId,\n } satisfies ConfigurationRepairBridge as unknown as Record<string, unknown>);\n // assurance-control: WILDO.ACCESS.CROSS_TENANT_ADMINISTRATION — the repair changes only what the schema refuses in one scope's configuration, each block by a rule that lifts no control, recorded with who and why.\n return outcome.blocks as Record<string, unknown>;\n },\n postfixCoreOperations: async (_id, updatedRow, executionContext, _operationPath, utils) => {\n const bridge = takeBridged(bridgeKey(variant.resourceType, SsoConfig_Operations.REPAIR_UNREADABLE_CONFIGURATION, executionContext)) as unknown as ConfigurationRepairBridge | undefined;\n if (!bridge || !updatedRow) return updatedRow;\n await emitAuthorityChangeAuditWhenDurable({\n serviceOptions: utils.serviceOptions,\n effectKey: ['sso-configuration-repaired', bridge.ssoConfigId].join(':'),\n logger: utils.logger as LoggerService,\n failureContext: { ssoConfigId: bridge.ssoConfigId, scopeType: variant.scopeType, scopeId: bridge.scopeId },\n emit: async () => {\n const auditLogs = container.isBound(SAAS_SERVICE_TYPES.AuditLogsService) ? container.get<AuditLogsBackendService>(SAAS_SERVICE_TYPES.AuditLogsService) : undefined;\n await auditLogs?.logSsoConfigurationRepaired({\n scopeType: variant.scopeType,\n ...(variant.scopeType === AuthScopeType.ORGANIZATION ? { organizationId: bridge.scopeId } : { applicationId: bridge.scopeId }),\n ssoConfigId: bridge.ssoConfigId,\n repairs: bridge.repairs.map(({ path, action }) => ({ path: JSON.stringify(path), action })),\n routingRemoved: bridge.routingRemoved,\n providersAdmitted: bridge.providersAdmitted,\n repairedByUserId: bridge.repairedByUserId,\n justification: bridge.justification,\n }, executionContext);\n },\n });\n return {\n repairs: bridge.repairs,\n routingRemoved: bridge.routingRemoved,\n providersAdmitted: bridge.providersAdmitted,\n remainingFaults: bridge.remainingFaults,\n };\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\n/** The refusals that are about the row's STATE rather than the request's shape: 409, as the floors answer. */\nconst REPAIR_REFUSAL_IS_CONFLICT: ReadonlySet<SsoConfigRepairRefusal> = new Set([\n SsoConfigRepairRefusal.CONFIGURATION_READABLE,\n SsoConfigRepairRefusal.ROUTING_REMOVED_UNACKNOWLEDGED,\n SsoConfigRepairRefusal.PROVIDERS_ADMITTED_UNACKNOWLEDGED,\n SsoConfigRepairRefusal.EMERGENCY_ACCESS_NOT_REPAIRABLE,\n]);\n\n/** What each refusal tells the operator to do next. */\nconst REPAIR_REFUSAL_MESSAGES: Readonly<Record<SsoConfigRepairRefusal, string>> = {\n [SsoConfigRepairRefusal.CONFIGURATION_READABLE]:\n 'This scope\\'s single sign-on configuration reads, so there is nothing to repair here: its administrators change it through its own doors.',\n [SsoConfigRepairRefusal.PATH_NOT_FOUND]: 'A path named for repair is not in the stored configuration. The places the schema refuses are listed in `configurationFaults`.',\n [SsoConfigRepairRefusal.PATH_NOT_AT_FAULT]:\n 'A path named for repair is not one of the places the schema refuses, or inside one, so repairing it would change a part that reads. Only what is listed in `configurationFaults` may be repaired.',\n [SsoConfigRepairRefusal.PATHS_OVERLAP]: 'Two paths named for repair are the same, or one lies inside the other. Name each place once.',\n [SsoConfigRepairRefusal.STILL_UNREADABLE]: 'A block this repair touches would still not read. What remains is listed in `configurationFaults`.',\n [SsoConfigRepairRefusal.ROUTING_REMOVED_UNACKNOWLEDGED]:\n 'This repair stops routing the domains in `configurationRoutingRemoved` to this scope\\'s identity provider. Name each of them in `acknowledgedRoutingRemoved` to proceed.',\n [SsoConfigRepairRefusal.PROVIDERS_ADMITTED_UNACKNOWLEDGED]:\n 'This repair lets this scope\\'s members use the social providers in `configurationProvidersAdmitted`, which the stored restrictions refused. Name each of them in `acknowledgedProvidersAdmitted` to proceed.',\n [SsoConfigRepairRefusal.EMERGENCY_ACCESS_NOT_REPAIRABLE]:\n 'The break-glass block is never changed by this door: removing an entry takes a way in away and adding one grants it. Restore the stored row out of band, and record why.',\n [SsoConfigRepairRefusal.OVERRIDE_NOT_REMOVABLE]:\n 'A social credential override that reads and has no duplicate is never removed: it holds the scope\\'s own sealed credentials. Name a duplicate, or an entry listed in `configurationFaults`.',\n};\n\n// ════════════════════════════════════════════════════\n// describeUnreadableFields (#3349)\n// ════════════════════════════════════════════════════\n\n/**\n * What of the scope's configuration does not read, for its own administrators: paths and the schema's messages, never a\n * value. REPLACE: the core READ fails on exactly the row this answers about (#3344). Read raw and confined to the scope,\n * as the repair reads it. An empty list for a row that reads.\n */\nfunction createDescribeUnreadableFieldsFactory(variant: SsoConfigScopeVariant): ResourceCustomServiceImplementationFactory {\n const factory = (_resourcesRegistryService: ResourcesRegistryBackendService, container: Container) =>\n createResourceCustomServiceImplementation({\n operationPath: {\n resourceIdentifier: variant.resourceType,\n operationIdentifier: SsoConfig_Operations.DESCRIBE_UNREADABLE_FIELDS,\n variantType: ResourceOperationVariantType.API_CALL,\n isOperationDefault: true,\n },\n debugLabel: `${variant.resourceType}.describeUnreadableFields`,\n handlers: {\n replaceCoreOperations: async (id, _input, executionContext, _operationPath, utils) => {\n const { stored } = await readConfinedStoredRow(variant, container, executionContext, utils, typeof id === 'string' && id.length > 0 ? id : undefined);\n return { unreadableFields: ssoConfigBlockFaults(stored).map(({ block, path, message }) => ({ block, path, message })) };\n },\n },\n });\n return factory as unknown as ResourceCustomServiceImplementationFactory;\n}\n\nexport function createSsoConfigDomainVerificationFactories(): ResourceCustomServiceImplementationFactory[] {\n return SSO_CONFIG_SCOPE_VARIANTS.flatMap((variant) => [\n createClaimDomainFactory(variant),\n createVerifyDomainFactory(variant),\n createRevokeDomainFactory(variant),\n createDomainSsoRoutingFactory(variant, true),\n createDomainSsoRoutingFactory(variant, false),\n createRepairUnreadableConfigurationFactory(variant),\n ]);\n}\n\n/**\n * The administrator's read of what does not read (#3349), at both scopes. Its own export, beside the writing verbs above\n * rather than among them: it writes nothing, so the version pin every one of them carries (#3279) has nothing to pin.\n */\nexport function createSsoConfigUnreadableFieldsFactories(): ResourceCustomServiceImplementationFactory[] {\n return SSO_CONFIG_SCOPE_VARIANTS.map((variant) => createDescribeUnreadableFieldsFactory(variant));\n}\n"]}
@@ -65,10 +65,34 @@
65
65
  * unadministrable is an availability incident, not a completed data-protection request. The
66
66
  * operator appoints a successor and then erases; {@link SUPER_ADMIN_FLOOR_REMEDY} is the text that
67
67
  * says so.
68
+ *
69
+ * ## Concurrent reductions are serialized on the APPLICATION row (#3670)
70
+ *
71
+ * A count-then-write guard is open to write skew: administrator A removes B while B removes A, each
72
+ * measures the other still present, both commit, and the application has none. No extra check closes
73
+ * that, because each transaction's view is internally consistent. So, given the reducing operation's
74
+ * `transaction`, the floor first bumps `Application.superAdminFloorSerializationToken` inside it and
75
+ * only then measures: two concurrent reductions write the same row, and the store makes the second wait
76
+ * (PostgreSQL) or retry (MongoDB) until the first has committed, after which its measurement sees the
77
+ * removal. See {@link bumpSuperAdminFloorSerializationToken}.
78
+ *
79
+ * The collision exists only INSIDE the callers' transactions, so every reducing door forwards its own:
80
+ *
81
+ * | door | transaction |
82
+ * |---|---|
83
+ * | `users / assign_roles`, `revoke_roles` | `transactionalCore` on the role-administration registration |
84
+ * | `users / update` (`appRoles`) | `transactionalCore` on the floor's UPDATE registration |
85
+ * | `users / delete` | the audited write's own transaction (#2297), whenever the post-commit outbox can capture it |
86
+ * | the account-lifecycle verbs (`suspend_user`, `deactivate_account`, …) | their `transactionalCore` |
87
+ * | subject erasure | none: its guard runs before the erasure's writes, outside any transaction, so it stays unserialized, exactly as the organization owner floor's erasure guard does |
88
+ *
89
+ * Without a transaction the bump is skipped rather than autocommitted: outside one it serializes nothing
90
+ * and would only add a write.
68
91
  */
69
- import { UserStatus, type User } from '@wildo-ai/saas-models';
92
+ import { CoreResourceType, UserStatus, type User } from '@wildo-ai/saas-models';
70
93
  import type { Container } from 'inversify';
71
94
  import type { ExecutionContext } from '../../runtime/models/execution-context.backend.schemas';
95
+ import type { TransactionContext } from '../../databases/models/transaction.shared.schemas';
72
96
  import type { ErrorBuilderBackendService } from '../../errors/services/error-builder.backend.service';
73
97
  import type { AuthorizationsBackendService } from '../../security/authorizations/services/authorizations.backend.service';
74
98
  import type { RepositoriesRegistryHandlerBackendService } from '../../base-classes/services/repositories/repositories-registry-handler.backend.service';
@@ -205,7 +229,36 @@ export declare function countOtherUsableSuperAdmins(params: {
205
229
  errorBuilder: ErrorBuilderBackendService;
206
230
  conferringRoles: readonly string[];
207
231
  operationIdentifier: string;
232
+ /** The reducing operation's transaction. Measured inside it, a concurrent removal it has waited on is counted as gone. */
233
+ transaction?: TransactionContext;
208
234
  }): Promise<number>;
235
+ /**
236
+ * The resources the floor writes or reads inside a caller's transaction, for a transactional-core registration's
237
+ * `transactionParticipants`: the APPLICATION row it bumps and the USERS rows it measures. A registration whose own
238
+ * resource is one of them may leave that one out (the framework includes the operation's resource).
239
+ */
240
+ export declare const SUPER_ADMIN_FLOOR_TRANSACTION_PARTICIPANTS: Readonly<Record<string, CoreResourceType>>;
241
+ /** The reason a reduction is refused when the row it must serialize on cannot be written. */
242
+ export declare const SUPER_ADMIN_FLOOR_SERIALIZATION_ANCHOR_MISSING_REASON = "super_admin_floor_serialization_anchor_missing";
243
+ /**
244
+ * Write the application's super-administrator serialization token inside the reducing transaction (#3670).
245
+ *
246
+ * An atomic increment through the infrastructure tier: no execution context has to be allowed to write APPLICATION (the
247
+ * outer operation already decided who may reduce the population; this is a mechanism, not a second permission
248
+ * question), and the strict request re-parse that would strip an `.excludeFromUpdate()` field never runs. The value is
249
+ * irrelevant; what matters is that the row is WRITTEN in the transaction, which is what two reductions collide on.
250
+ *
251
+ * Fails CLOSED when no APPLICATION row was written. Every running application holds exactly one, so its absence is a
252
+ * misconfigured store, and proceeding would put the check-then-act back with nothing serializing it, on a failure that
253
+ * has no repair from above. The refusal costs a demotion that can be retried; the race costs the application.
254
+ */
255
+ export declare function bumpSuperAdminFloorSerializationToken(params: {
256
+ transaction: TransactionContext;
257
+ executionContext: ExecutionContext<any>;
258
+ repositoriesRegistry: RepositoriesRegistryHandlerBackendService;
259
+ errorBuilder: ErrorBuilderBackendService;
260
+ operationIdentifier: string;
261
+ }): Promise<void>;
209
262
  /**
210
263
  * Refuse a write that would leave the application without an administratively usable
211
264
  * super-administrator.
@@ -240,6 +293,12 @@ export declare function assertSuperAdminFloorPreserved(params: {
240
293
  errorBuilder: ErrorBuilderBackendService;
241
294
  conferringRoles: readonly string[];
242
295
  operationIdentifier: string;
296
+ /**
297
+ * The transaction of the operation reducing the population. With it, the floor serializes against every other
298
+ * reduction (see the module header) and measures inside it; without it, nothing serializes the check-then-act.
299
+ * A prefix holds it as `utils.serviceOptions.transaction`.
300
+ */
301
+ transaction?: TransactionContext;
243
302
  }): Promise<void>;
244
303
  /**
245
304
  * The floor check for a role/status TRANSITION on a single subject.
@@ -266,6 +325,8 @@ export declare function assertSuperAdminFloorPreservedForTransition(params: {
266
325
  errorBuilder: ErrorBuilderBackendService;
267
326
  conferringRoles: readonly string[];
268
327
  operationIdentifier: string;
328
+ /** See {@link assertSuperAdminFloorPreserved}. */
329
+ transaction?: TransactionContext;
269
330
  }): Promise<void>;
270
331
  /**
271
332
  * The floor check for a write that removes the subject's row wholesale — a hard DELETE or a subject
@@ -283,6 +344,8 @@ export declare function assertSuperAdminFloorPreservedForRemoval(params: {
283
344
  errorBuilder: ErrorBuilderBackendService;
284
345
  conferringRoles: readonly string[];
285
346
  operationIdentifier: string;
347
+ /** See {@link assertSuperAdminFloorPreserved}. */
348
+ transaction?: TransactionContext;
286
349
  }): Promise<void>;
287
350
  /**
288
351
  * The resource types whose rows carry the application authority axis, and therefore the subject
@@ -1 +1 @@
1
- {"version":3,"file":"super-admin-floor.backend.utils.d.ts","sourceRoot":"","sources":["../../../../src/security/authorizations/super-admin-floor.backend.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AAEH,OAAO,EAQL,UAAU,EACV,KAAK,IAAI,EACV,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qEAAqE,CAAC;AAC5G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kEAAkE,CAAC;AACnH,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oFAAoF,CAAC;AACvI,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,qGAAqG,CAAC;AAIrK;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qCAAqC,EAAE,SAAS,UAAU,EAAwB,CAAC;AAEhG;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,4FACsD,CAAC;AAE5F;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,2BAA2B,CAAC;AAEzE;;;;GAIG;AACH,oBAAY,6BAA6B;IACvC,mEAAmE;IACnE,YAAY,iBAAiB;IAC7B,gEAAgE;IAChE,aAAa,kBAAkB;IAC/B,4CAA4C;IAC5C,QAAQ,aAAa;IACrB,gEAAgE;IAChE,OAAO,YAAY;CACpB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,2BAA2B,GAAG,MAAM,MAAM,EAAE,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,wBAAgB,gCAAgC,CAC9C,qBAAqB,EAAE,IAAI,CAAC,4BAA4B,EAAE,aAAa,GAAG,kBAAkB,CAAC,GAC5F,MAAM,EAAE,CAOV;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAAC,SAAS,EAAE,SAAS,GAAG,2BAA2B,CAMnG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIjG;AAED,oHAAoH;AACpH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAEvE;AAED,mGAAmG;AACnG,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,CAAC,GAAG,SAAS,GAAG,IAAI,EAC1D,eAAe,EAAE,SAAS,MAAM,EAAE,GACjC,OAAO,CAGT;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,2BAA2B,CAAC,MAAM,EAAE;IACxD,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BlB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,8BAA8B,CAAC,MAAM,EAAE;IAC3D,+FAA+F;IAC/F,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,KAAK,EAAE,6BAA6B,CAAC;IACrC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC;;;;;;;;;;;OAWG;IACH,iCAAiC,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IACzE,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ChB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,2CAA2C,CAAC,MAAM,EAAE;IACxE,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,uGAAuG;IACvG,iCAAiC,CAAC,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IACzE,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBhB;AAED;;;;;;;GAOG;AACH,wBAAsB,wCAAwC,CAAC,MAAM,EAAE;IACrE,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,GAAG,QAAQ,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC;IACpF,KAAK,EAAE,6BAA6B,CAAC;IACrC,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iDAAiD,EAAE,SAAS,MAAM,EAG9E,CAAC;AAEF,sGAAsG;AACtG,wBAAgB,wCAAwC,CAAC,YAAY,EAAE,OAAO,GAAG,OAAO,CAEvF;AAED;;;;;;;;GAQG;AACH,wBAAsB,8BAA8B,CAAC,MAAM,EAAE;IAC3D,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,GAAG,QAAQ,CAAC,EAAE,CAAC,CAqBvD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iCAAiC,CAAC,MAAM,EAAE;IAC9D,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,GAAG,OAAO,CAAC;IAAE,qBAAqB,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAe7F;AAED,iFAAiF;AACjF,MAAM,MAAM,qBAAqB,GAAG;IAClC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,sCAAsC,CAAC,MAAM,EAAE;IACnE,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,UAAU,GAAG,QAAQ,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC;IACpF,gBAAgB,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACxC,oBAAoB,EAAE,yCAAyC,CAAC;IAChE,YAAY,EAAE,0BAA0B,CAAC;IACzC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8FAA8F;IAC9F,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mFAAmF;IACnF,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAChF,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB"}
1
+ {"version":3,"file":"super-admin-floor.backend.utils.d.ts","sourceRoot":"","sources":["../../../../src/security/authorizations/super-admin-floor.backend.utils.ts"],"names":[],"mappings":"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"}
@@ -65,6 +65,29 @@
65
65
  * unadministrable is an availability incident, not a completed data-protection request. The
66
66
  * operator appoints a successor and then erases; {@link SUPER_ADMIN_FLOOR_REMEDY} is the text that
67
67
  * says so.
68
+ *
69
+ * ## Concurrent reductions are serialized on the APPLICATION row (#3670)
70
+ *
71
+ * A count-then-write guard is open to write skew: administrator A removes B while B removes A, each
72
+ * measures the other still present, both commit, and the application has none. No extra check closes
73
+ * that, because each transaction's view is internally consistent. So, given the reducing operation's
74
+ * `transaction`, the floor first bumps `Application.superAdminFloorSerializationToken` inside it and
75
+ * only then measures: two concurrent reductions write the same row, and the store makes the second wait
76
+ * (PostgreSQL) or retry (MongoDB) until the first has committed, after which its measurement sees the
77
+ * removal. See {@link bumpSuperAdminFloorSerializationToken}.
78
+ *
79
+ * The collision exists only INSIDE the callers' transactions, so every reducing door forwards its own:
80
+ *
81
+ * | door | transaction |
82
+ * |---|---|
83
+ * | `users / assign_roles`, `revoke_roles` | `transactionalCore` on the role-administration registration |
84
+ * | `users / update` (`appRoles`) | `transactionalCore` on the floor's UPDATE registration |
85
+ * | `users / delete` | the audited write's own transaction (#2297), whenever the post-commit outbox can capture it |
86
+ * | the account-lifecycle verbs (`suspend_user`, `deactivate_account`, …) | their `transactionalCore` |
87
+ * | subject erasure | none: its guard runs before the erasure's writes, outside any transaction, so it stays unserialized, exactly as the organization owner floor's erasure guard does |
88
+ *
89
+ * Without a transaction the bump is skipped rather than autocommitted: outside one it serializes nothing
90
+ * and would only add a write.
68
91
  */
69
92
  import { AdministrativeContinuityErrorCode, CORE_APP_ROLES, CoreResourceOperation, CoreResourceType, ErrorCustomMessageReference, ErrorType, ResourcePrimaryScope, UserStatus, } from '@wildo-ai/saas-models';
70
93
  import { SAAS_SERVICE_TYPES } from '../../inject/models/service-types.js';
@@ -230,11 +253,61 @@ export async function countOtherUsableSuperAdmins(params) {
230
253
  const candidates = await userRepository.list(executionContext, {
231
254
  appRoles: { $in: [...conferringRoles] },
232
255
  status: { $in: [...ADMINISTRATIVELY_USABLE_USER_STATUSES] },
233
- });
256
+ }, params.transaction ? { transaction: params.transaction } : undefined);
234
257
  const excludedSubjectIdSet = new Set(excludedSubjectIds.map((subjectId) => String(subjectId)));
235
258
  const rows = Array.isArray(candidates) ? candidates : [];
236
259
  return rows.filter((row) => !excludedSubjectIdSet.has(String(row?._id))).length;
237
260
  }
261
+ /**
262
+ * The resources the floor writes or reads inside a caller's transaction, for a transactional-core registration's
263
+ * `transactionParticipants`: the APPLICATION row it bumps and the USERS rows it measures. A registration whose own
264
+ * resource is one of them may leave that one out (the framework includes the operation's resource).
265
+ */
266
+ export const SUPER_ADMIN_FLOOR_TRANSACTION_PARTICIPANTS = Object.freeze({
267
+ application: CoreResourceType.APPLICATION,
268
+ users: CoreResourceType.USERS,
269
+ });
270
+ /** The reason a reduction is refused when the row it must serialize on cannot be written. */
271
+ export const SUPER_ADMIN_FLOOR_SERIALIZATION_ANCHOR_MISSING_REASON = 'super_admin_floor_serialization_anchor_missing';
272
+ /**
273
+ * Write the application's super-administrator serialization token inside the reducing transaction (#3670).
274
+ *
275
+ * An atomic increment through the infrastructure tier: no execution context has to be allowed to write APPLICATION (the
276
+ * outer operation already decided who may reduce the population; this is a mechanism, not a second permission
277
+ * question), and the strict request re-parse that would strip an `.excludeFromUpdate()` field never runs. The value is
278
+ * irrelevant; what matters is that the row is WRITTEN in the transaction, which is what two reductions collide on.
279
+ *
280
+ * Fails CLOSED when no APPLICATION row was written. Every running application holds exactly one, so its absence is a
281
+ * misconfigured store, and proceeding would put the check-then-act back with nothing serializing it, on a failure that
282
+ * has no repair from above. The refusal costs a demotion that can be retried; the race costs the application.
283
+ */
284
+ export async function bumpSuperAdminFloorSerializationToken(params) {
285
+ const { transaction, executionContext, repositoriesRegistry, errorBuilder, operationIdentifier } = params;
286
+ // Addressed by id, read in the same transaction: PostgreSQL's guarded write refuses an unfiltered UPDATE, and the id
287
+ // form is the one both adapters cast alike. A store holds one APPLICATION row; several would all be written, which still
288
+ // gives every reduction the same row to collide on.
289
+ const applicationIds = repositoriesRegistry.getRepository(CoreResourceType.APPLICATION)
290
+ ? (await repositoriesRegistry.findManyForInfrastructure(CoreResourceType.APPLICATION, {}, executionContext, { transaction }))
291
+ .map((row) => row?._id)
292
+ .filter((id) => id !== undefined && id !== null)
293
+ .map((id) => String(id))
294
+ : [];
295
+ const written = applicationIds.length > 0
296
+ ? await repositoriesRegistry.bulkUpdateForInfrastructure(CoreResourceType.APPLICATION, { _id: { $in: applicationIds } }, { increment: { superAdminFloorSerializationToken: 1 } }, executionContext, { transaction })
297
+ : 0;
298
+ if (written > 0)
299
+ return;
300
+ throw errorBuilder.buildError(ErrorType.CONFIGURATION, executionContext, {
301
+ context: {
302
+ reason: SUPER_ADMIN_FLOOR_SERIALIZATION_ANCHOR_MISSING_REASON,
303
+ message: 'Cannot evaluate the super-administrator floor: the APPLICATION row that concurrent reductions serialize on '
304
+ + 'could not be written, so two removals could not be made to collide. Refusing rather than removing an '
305
+ + 'administrator without that guarantee.',
306
+ resourceType: CoreResourceType.APPLICATION,
307
+ operationIdentifier,
308
+ },
309
+ });
310
+ }
238
311
  /**
239
312
  * Refuse a write that would leave the application without an administratively usable
240
313
  * super-administrator.
@@ -248,7 +321,13 @@ export async function countOtherUsableSuperAdmins(params) {
248
321
  * one by the operation's own error path.
249
322
  */
250
323
  export async function assertSuperAdminFloorPreserved(params) {
251
- const { subjectUserIds, cause, executionContext, repositoriesRegistry, errorBuilder, conferringRoles, operationIdentifier } = params;
324
+ const { subjectUserIds, cause, executionContext, repositoriesRegistry, errorBuilder, conferringRoles, operationIdentifier, transaction } = params;
325
+ // BEFORE the measurement, so the conflict window covers the whole check-then-act rather than only the write at the end.
326
+ // assurance-control: WILDO.ACCESS.ADMINISTRATIVE_CONTINUITY — serialize concurrent reductions of the application's
327
+ // administrative population.
328
+ if (transaction) {
329
+ await bumpSuperAdminFloorSerializationToken({ transaction, executionContext, repositoriesRegistry, errorBuilder, operationIdentifier });
330
+ }
252
331
  const remainingUsableSuperAdmins = await countOtherUsableSuperAdmins({
253
332
  excludedSubjectIds: subjectUserIds,
254
333
  executionContext: params.resolvePopulationExecutionContext
@@ -258,6 +337,7 @@ export async function assertSuperAdminFloorPreserved(params) {
258
337
  errorBuilder,
259
338
  conferringRoles,
260
339
  operationIdentifier,
340
+ transaction,
261
341
  });
262
342
  if (remainingUsableSuperAdmins >= SUPER_ADMIN_FLOOR_MINIMUM)
263
343
  return;
@@ -319,6 +399,7 @@ export async function assertSuperAdminFloorPreservedForTransition(params) {
319
399
  errorBuilder,
320
400
  conferringRoles,
321
401
  operationIdentifier,
402
+ transaction: params.transaction,
322
403
  });
323
404
  }
324
405
  /**
@@ -344,6 +425,7 @@ export async function assertSuperAdminFloorPreservedForRemoval(params) {
344
425
  errorBuilder,
345
426
  conferringRoles,
346
427
  operationIdentifier,
428
+ transaction: params.transaction,
347
429
  });
348
430
  }
349
431
  /**