@aglyn/tenant-data-admin 1.0.0-beta.143

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 (374) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/jest.integration.config.d.ts +39 -0
  4. package/jest.integration.setup.d.ts +17 -0
  5. package/package.json +51 -0
  6. package/src/index.d.ts +17 -0
  7. package/src/index.js +18 -0
  8. package/src/index.js.map +1 -0
  9. package/src/lib/render-cache.d.ts +184 -0
  10. package/src/lib/render-cache.js +198 -0
  11. package/src/lib/render-cache.js.map +1 -0
  12. package/src/lib/server/account-addresses.d.ts +160 -0
  13. package/src/lib/server/account-addresses.js +311 -0
  14. package/src/lib/server/account-addresses.js.map +1 -0
  15. package/src/lib/server/account-emails.d.ts +219 -0
  16. package/src/lib/server/account-emails.js +640 -0
  17. package/src/lib/server/account-emails.js.map +1 -0
  18. package/src/lib/server/admin-audit.d.ts +180 -0
  19. package/src/lib/server/admin-audit.js +233 -0
  20. package/src/lib/server/admin-audit.js.map +1 -0
  21. package/src/lib/server/analytics-retention.d.ts +63 -0
  22. package/src/lib/server/analytics-retention.js +66 -0
  23. package/src/lib/server/analytics-retention.js.map +1 -0
  24. package/src/lib/server/api-http.d.ts +159 -0
  25. package/src/lib/server/api-http.js +230 -0
  26. package/src/lib/server/api-http.js.map +1 -0
  27. package/src/lib/server/api-keys.d.ts +117 -0
  28. package/src/lib/server/api-keys.js +298 -0
  29. package/src/lib/server/api-keys.js.map +1 -0
  30. package/src/lib/server/auth-handoff.d.ts +165 -0
  31. package/src/lib/server/auth-handoff.js +482 -0
  32. package/src/lib/server/auth-handoff.js.map +1 -0
  33. package/src/lib/server/auth-pools.d.ts +246 -0
  34. package/src/lib/server/auth-pools.js +551 -0
  35. package/src/lib/server/auth-pools.js.map +1 -0
  36. package/src/lib/server/billing-addons.d.ts +171 -0
  37. package/src/lib/server/billing-addons.js +277 -0
  38. package/src/lib/server/billing-addons.js.map +1 -0
  39. package/src/lib/server/campaign-attribution-store.d.ts +55 -0
  40. package/src/lib/server/campaign-attribution-store.js +95 -0
  41. package/src/lib/server/campaign-attribution-store.js.map +1 -0
  42. package/src/lib/server/campaign-conversion-attribution.d.ts +205 -0
  43. package/src/lib/server/campaign-conversion-attribution.js +279 -0
  44. package/src/lib/server/campaign-conversion-attribution.js.map +1 -0
  45. package/src/lib/server/client-error-report.d.ts +301 -0
  46. package/src/lib/server/client-error-report.js +755 -0
  47. package/src/lib/server/client-error-report.js.map +1 -0
  48. package/src/lib/server/connect-account-status.d.ts +74 -0
  49. package/src/lib/server/connect-account-status.js +94 -0
  50. package/src/lib/server/connect-account-status.js.map +1 -0
  51. package/src/lib/server/connect-payout-failure.d.ts +103 -0
  52. package/src/lib/server/connect-payout-failure.js +127 -0
  53. package/src/lib/server/connect-payout-failure.js.map +1 -0
  54. package/src/lib/server/console-api-rate-limit.d.ts +81 -0
  55. package/src/lib/server/console-api-rate-limit.js +111 -0
  56. package/src/lib/server/console-api-rate-limit.js.map +1 -0
  57. package/src/lib/server/console-domains.d.ts +326 -0
  58. package/src/lib/server/console-domains.js +779 -0
  59. package/src/lib/server/console-domains.js.map +1 -0
  60. package/src/lib/server/consume-once.d.ts +91 -0
  61. package/src/lib/server/consume-once.js +96 -0
  62. package/src/lib/server/consume-once.js.map +1 -0
  63. package/src/lib/server/contact-company-link.d.ts +85 -0
  64. package/src/lib/server/contact-company-link.js +105 -0
  65. package/src/lib/server/contact-company-link.js.map +1 -0
  66. package/src/lib/server/contact-email-engagement.d.ts +32 -0
  67. package/src/lib/server/contact-email-engagement.js +145 -0
  68. package/src/lib/server/contact-email-engagement.js.map +1 -0
  69. package/src/lib/server/contact-email-index.d.ts +56 -0
  70. package/src/lib/server/contact-email-index.js +158 -0
  71. package/src/lib/server/contact-email-index.js.map +1 -0
  72. package/src/lib/server/contact-lifecycle-floor.d.ts +89 -0
  73. package/src/lib/server/contact-lifecycle-floor.js +88 -0
  74. package/src/lib/server/contact-lifecycle-floor.js.map +1 -0
  75. package/src/lib/server/contact-merge.d.ts +55 -0
  76. package/src/lib/server/contact-merge.js +279 -0
  77. package/src/lib/server/contact-merge.js.map +1 -0
  78. package/src/lib/server/contact-suppression.d.ts +153 -0
  79. package/src/lib/server/contact-suppression.js +259 -0
  80. package/src/lib/server/contact-suppression.js.map +1 -0
  81. package/src/lib/server/crm-booking-activity.d.ts +86 -0
  82. package/src/lib/server/crm-booking-activity.js +251 -0
  83. package/src/lib/server/crm-booking-activity.js.map +1 -0
  84. package/src/lib/server/crm-email-activity.d.ts +112 -0
  85. package/src/lib/server/crm-email-activity.js +143 -0
  86. package/src/lib/server/crm-email-activity.js.map +1 -0
  87. package/src/lib/server/crm-inbound-email.d.ts +145 -0
  88. package/src/lib/server/crm-inbound-email.js +287 -0
  89. package/src/lib/server/crm-inbound-email.js.map +1 -0
  90. package/src/lib/server/crm-next-activity.d.ts +74 -0
  91. package/src/lib/server/crm-next-activity.js +194 -0
  92. package/src/lib/server/crm-next-activity.js.map +1 -0
  93. package/src/lib/server/crm-records.d.ts +144 -0
  94. package/src/lib/server/crm-records.js +218 -0
  95. package/src/lib/server/crm-records.js.map +1 -0
  96. package/src/lib/server/csp-aggregate.d.ts +62 -0
  97. package/src/lib/server/csp-aggregate.js +276 -0
  98. package/src/lib/server/csp-aggregate.js.map +1 -0
  99. package/src/lib/server/data-storage-gate.d.ts +66 -0
  100. package/src/lib/server/data-storage-gate.js +48 -0
  101. package/src/lib/server/data-storage-gate.js.map +1 -0
  102. package/src/lib/server/dataset-live-pages.d.ts +179 -0
  103. package/src/lib/server/dataset-live-pages.js +421 -0
  104. package/src/lib/server/dataset-live-pages.js.map +1 -0
  105. package/src/lib/server/dns-probe.d.ts +53 -0
  106. package/src/lib/server/dns-probe.js +184 -0
  107. package/src/lib/server/dns-probe.js.map +1 -0
  108. package/src/lib/server/document-id.d.ts +29 -0
  109. package/src/lib/server/document-id.js +100 -0
  110. package/src/lib/server/document-id.js.map +1 -0
  111. package/src/lib/server/domain-provider-vercel.d.ts +33 -0
  112. package/src/lib/server/domain-provider-vercel.js +298 -0
  113. package/src/lib/server/domain-provider-vercel.js.map +1 -0
  114. package/src/lib/server/domain-provider-webhook.d.ts +73 -0
  115. package/src/lib/server/domain-provider-webhook.js +223 -0
  116. package/src/lib/server/domain-provider-webhook.js.map +1 -0
  117. package/src/lib/server/domain-provider-wildcard.d.ts +54 -0
  118. package/src/lib/server/domain-provider-wildcard.js +163 -0
  119. package/src/lib/server/domain-provider-wildcard.js.map +1 -0
  120. package/src/lib/server/domain-provider.d.ts +197 -0
  121. package/src/lib/server/domain-provider.js +221 -0
  122. package/src/lib/server/domain-provider.js.map +1 -0
  123. package/src/lib/server/duplicate-activity.d.ts +54 -0
  124. package/src/lib/server/duplicate-activity.js +67 -0
  125. package/src/lib/server/duplicate-activity.js.map +1 -0
  126. package/src/lib/server/duplicate-resource.d.ts +55 -0
  127. package/src/lib/server/duplicate-resource.js +474 -0
  128. package/src/lib/server/duplicate-resource.js.map +1 -0
  129. package/src/lib/server/dynamic-list-materialize.d.ts +153 -0
  130. package/src/lib/server/dynamic-list-materialize.js +581 -0
  131. package/src/lib/server/dynamic-list-materialize.js.map +1 -0
  132. package/src/lib/server/edit-access-authz.d.ts +56 -0
  133. package/src/lib/server/edit-access-authz.js +107 -0
  134. package/src/lib/server/edit-access-authz.js.map +1 -0
  135. package/src/lib/server/edit-access-token.d.ts +72 -0
  136. package/src/lib/server/edit-access-token.js +116 -0
  137. package/src/lib/server/edit-access-token.js.map +1 -0
  138. package/src/lib/server/edit-hint-token.d.ts +83 -0
  139. package/src/lib/server/edit-hint-token.js +119 -0
  140. package/src/lib/server/edit-hint-token.js.map +1 -0
  141. package/src/lib/server/email-delivery-log.d.ts +509 -0
  142. package/src/lib/server/email-delivery-log.js +1043 -0
  143. package/src/lib/server/email-delivery-log.js.map +1 -0
  144. package/src/lib/server/email-flow-gate.d.ts +80 -0
  145. package/src/lib/server/email-flow-gate.js +153 -0
  146. package/src/lib/server/email-flow-gate.js.map +1 -0
  147. package/src/lib/server/email-marketing-gate.d.ts +333 -0
  148. package/src/lib/server/email-marketing-gate.js +639 -0
  149. package/src/lib/server/email-marketing-gate.js.map +1 -0
  150. package/src/lib/server/email-metering.d.ts +293 -0
  151. package/src/lib/server/email-metering.js +359 -0
  152. package/src/lib/server/email-metering.js.map +1 -0
  153. package/src/lib/server/email-revenue-attribution.d.ts +185 -0
  154. package/src/lib/server/email-revenue-attribution.js +300 -0
  155. package/src/lib/server/email-revenue-attribution.js.map +1 -0
  156. package/src/lib/server/email-send-rate.d.ts +232 -0
  157. package/src/lib/server/email-send-rate.js +417 -0
  158. package/src/lib/server/email-send-rate.js.map +1 -0
  159. package/src/lib/server/email-sender-reputation.d.ts +317 -0
  160. package/src/lib/server/email-sender-reputation.js +464 -0
  161. package/src/lib/server/email-sender-reputation.js.map +1 -0
  162. package/src/lib/server/email-suppression.d.ts +490 -0
  163. package/src/lib/server/email-suppression.js +648 -0
  164. package/src/lib/server/email-suppression.js.map +1 -0
  165. package/src/lib/server/email-topic-confirmation.d.ts +150 -0
  166. package/src/lib/server/email-topic-confirmation.js +272 -0
  167. package/src/lib/server/email-topic-confirmation.js.map +1 -0
  168. package/src/lib/server/email-unsubscribe-link.d.ts +174 -0
  169. package/src/lib/server/email-unsubscribe-link.js +236 -0
  170. package/src/lib/server/email-unsubscribe-link.js.map +1 -0
  171. package/src/lib/server/erase-person.d.ts +116 -0
  172. package/src/lib/server/erase-person.js +272 -0
  173. package/src/lib/server/erase-person.js.map +1 -0
  174. package/src/lib/server/erase.d.ts +458 -0
  175. package/src/lib/server/erase.js +1506 -0
  176. package/src/lib/server/erase.js.map +1 -0
  177. package/src/lib/server/firebase-admin.d.ts +71 -0
  178. package/src/lib/server/firebase-admin.js +343 -0
  179. package/src/lib/server/firebase-admin.js.map +1 -0
  180. package/src/lib/server/form-dataset-binding-token.d.ts +35 -0
  181. package/src/lib/server/form-dataset-binding-token.js +107 -0
  182. package/src/lib/server/form-dataset-binding-token.js.map +1 -0
  183. package/src/lib/server/free-workspace-cap.d.ts +201 -0
  184. package/src/lib/server/free-workspace-cap.js +404 -0
  185. package/src/lib/server/free-workspace-cap.js.map +1 -0
  186. package/src/lib/server/ga4-measurement-protocol.d.ts +256 -0
  187. package/src/lib/server/ga4-measurement-protocol.js +558 -0
  188. package/src/lib/server/ga4-measurement-protocol.js.map +1 -0
  189. package/src/lib/server/host-email-tokens.d.ts +47 -0
  190. package/src/lib/server/host-email-tokens.js +72 -0
  191. package/src/lib/server/host-email-tokens.js.map +1 -0
  192. package/src/lib/server/host-memberships.d.ts +54 -0
  193. package/src/lib/server/host-memberships.js +194 -0
  194. package/src/lib/server/host-memberships.js.map +1 -0
  195. package/src/lib/server/host-sending-domain.d.ts +292 -0
  196. package/src/lib/server/host-sending-domain.js +451 -0
  197. package/src/lib/server/host-sending-domain.js.map +1 -0
  198. package/src/lib/server/host-visitor-records.d.ts +150 -0
  199. package/src/lib/server/host-visitor-records.js +262 -0
  200. package/src/lib/server/host-visitor-records.js.map +1 -0
  201. package/src/lib/server/id-token-refusal.d.ts +28 -0
  202. package/src/lib/server/id-token-refusal.js +111 -0
  203. package/src/lib/server/id-token-refusal.js.map +1 -0
  204. package/src/lib/server/legal-acceptance.d.ts +214 -0
  205. package/src/lib/server/legal-acceptance.js +305 -0
  206. package/src/lib/server/legal-acceptance.js.map +1 -0
  207. package/src/lib/server/list-members.d.ts +211 -0
  208. package/src/lib/server/list-members.js +176 -0
  209. package/src/lib/server/list-members.js.map +1 -0
  210. package/src/lib/server/live-page-usage.d.ts +202 -0
  211. package/src/lib/server/live-page-usage.js +300 -0
  212. package/src/lib/server/live-page-usage.js.map +1 -0
  213. package/src/lib/server/lockdown.d.ts +313 -0
  214. package/src/lib/server/lockdown.js +643 -0
  215. package/src/lib/server/lockdown.js.map +1 -0
  216. package/src/lib/server/media-cdn-rate-limit.d.ts +188 -0
  217. package/src/lib/server/media-cdn-rate-limit.js +204 -0
  218. package/src/lib/server/media-cdn-rate-limit.js.map +1 -0
  219. package/src/lib/server/media-delivery.d.ts +267 -0
  220. package/src/lib/server/media-delivery.js +485 -0
  221. package/src/lib/server/media-delivery.js.map +1 -0
  222. package/src/lib/server/media-download-tokens.d.ts +161 -0
  223. package/src/lib/server/media-download-tokens.js +386 -0
  224. package/src/lib/server/media-download-tokens.js.map +1 -0
  225. package/src/lib/server/media-quarantine.d.ts +127 -0
  226. package/src/lib/server/media-quarantine.js +170 -0
  227. package/src/lib/server/media-quarantine.js.map +1 -0
  228. package/src/lib/server/media-signing.d.ts +126 -0
  229. package/src/lib/server/media-signing.js +159 -0
  230. package/src/lib/server/media-signing.js.map +1 -0
  231. package/src/lib/server/media-storage-path.d.ts +96 -0
  232. package/src/lib/server/media-storage-path.js +111 -0
  233. package/src/lib/server/media-storage-path.js.map +1 -0
  234. package/src/lib/server/media-strong-digest.d.ts +85 -0
  235. package/src/lib/server/media-strong-digest.js +190 -0
  236. package/src/lib/server/media-strong-digest.js.map +1 -0
  237. package/src/lib/server/media-tombstone.d.ts +276 -0
  238. package/src/lib/server/media-tombstone.js +421 -0
  239. package/src/lib/server/media-tombstone.js.map +1 -0
  240. package/src/lib/server/media-variants.d.ts +309 -0
  241. package/src/lib/server/media-variants.js +428 -0
  242. package/src/lib/server/media-variants.js.map +1 -0
  243. package/src/lib/server/member-email-aliases.d.ts +180 -0
  244. package/src/lib/server/member-email-aliases.js +420 -0
  245. package/src/lib/server/member-email-aliases.js.map +1 -0
  246. package/src/lib/server/member-photo.d.ts +88 -0
  247. package/src/lib/server/member-photo.js +185 -0
  248. package/src/lib/server/member-photo.js.map +1 -0
  249. package/src/lib/server/membership-recover-throttle.d.ts +211 -0
  250. package/src/lib/server/membership-recover-throttle.js +231 -0
  251. package/src/lib/server/membership-recover-throttle.js.map +1 -0
  252. package/src/lib/server/notifications.d.ts +55 -0
  253. package/src/lib/server/notifications.js +134 -0
  254. package/src/lib/server/notifications.js.map +1 -0
  255. package/src/lib/server/org-billing.d.ts +97 -0
  256. package/src/lib/server/org-billing.js +236 -0
  257. package/src/lib/server/org-billing.js.map +1 -0
  258. package/src/lib/server/organizations.d.ts +837 -0
  259. package/src/lib/server/organizations.js +1814 -0
  260. package/src/lib/server/organizations.js.map +1 -0
  261. package/src/lib/server/password-reset-throttle.d.ts +84 -0
  262. package/src/lib/server/password-reset-throttle.js +102 -0
  263. package/src/lib/server/password-reset-throttle.js.map +1 -0
  264. package/src/lib/server/personal-data-export.d.ts +241 -0
  265. package/src/lib/server/personal-data-export.js +858 -0
  266. package/src/lib/server/personal-data-export.js.map +1 -0
  267. package/src/lib/server/platform-domain-names.d.ts +62 -0
  268. package/src/lib/server/platform-domain-names.js +197 -0
  269. package/src/lib/server/platform-domain-names.js.map +1 -0
  270. package/src/lib/server/platform-marketing-consent.d.ts +133 -0
  271. package/src/lib/server/platform-marketing-consent.js +209 -0
  272. package/src/lib/server/platform-marketing-consent.js.map +1 -0
  273. package/src/lib/server/rate-limit-store.d.ts +702 -0
  274. package/src/lib/server/rate-limit-store.js +1220 -0
  275. package/src/lib/server/rate-limit-store.js.map +1 -0
  276. package/src/lib/server/realm-plugins.d.ts +67 -0
  277. package/src/lib/server/realm-plugins.js +250 -0
  278. package/src/lib/server/realm-plugins.js.map +1 -0
  279. package/src/lib/server/recaptcha-allowlist.d.ts +90 -0
  280. package/src/lib/server/recaptcha-allowlist.js +409 -0
  281. package/src/lib/server/recaptcha-allowlist.js.map +1 -0
  282. package/src/lib/server/release-flags.d.ts +105 -0
  283. package/src/lib/server/release-flags.js +183 -0
  284. package/src/lib/server/release-flags.js.map +1 -0
  285. package/src/lib/server/replay-erasures.d.ts +126 -0
  286. package/src/lib/server/replay-erasures.js +217 -0
  287. package/src/lib/server/replay-erasures.js.map +1 -0
  288. package/src/lib/server/resolve-people.d.ts +66 -0
  289. package/src/lib/server/resolve-people.js +112 -0
  290. package/src/lib/server/resolve-people.js.map +1 -0
  291. package/src/lib/server/safe-equal.d.ts +45 -0
  292. package/src/lib/server/safe-equal.js +58 -0
  293. package/src/lib/server/safe-equal.js.map +1 -0
  294. package/src/lib/server/sending-domain-debt.d.ts +127 -0
  295. package/src/lib/server/sending-domain-debt.js +268 -0
  296. package/src/lib/server/sending-domain-debt.js.map +1 -0
  297. package/src/lib/server/sending-domain-recheck.d.ts +151 -0
  298. package/src/lib/server/sending-domain-recheck.js +253 -0
  299. package/src/lib/server/sending-domain-recheck.js.map +1 -0
  300. package/src/lib/server/sending-domains.d.ts +364 -0
  301. package/src/lib/server/sending-domains.js +683 -0
  302. package/src/lib/server/sending-domains.js.map +1 -0
  303. package/src/lib/server/serve-media-cdn.d.ts +433 -0
  304. package/src/lib/server/serve-media-cdn.js +1370 -0
  305. package/src/lib/server/serve-media-cdn.js.map +1 -0
  306. package/src/lib/server/serve-plugin-fetch.d.ts +61 -0
  307. package/src/lib/server/serve-plugin-fetch.js +294 -0
  308. package/src/lib/server/serve-plugin-fetch.js.map +1 -0
  309. package/src/lib/server/sms-keywords.d.ts +63 -0
  310. package/src/lib/server/sms-keywords.js +146 -0
  311. package/src/lib/server/sms-keywords.js.map +1 -0
  312. package/src/lib/server/sso-break-glass-owners.d.ts +91 -0
  313. package/src/lib/server/sso-break-glass-owners.js +227 -0
  314. package/src/lib/server/sso-break-glass-owners.js.map +1 -0
  315. package/src/lib/server/sso-domain-policy.d.ts +140 -0
  316. package/src/lib/server/sso-domain-policy.js +239 -0
  317. package/src/lib/server/sso-domain-policy.js.map +1 -0
  318. package/src/lib/server/sso-drift-logic.d.ts +106 -0
  319. package/src/lib/server/sso-drift-logic.js +95 -0
  320. package/src/lib/server/sso-drift-logic.js.map +1 -0
  321. package/src/lib/server/sso-enforcement.d.ts +204 -0
  322. package/src/lib/server/sso-enforcement.js +309 -0
  323. package/src/lib/server/sso-enforcement.js.map +1 -0
  324. package/src/lib/server/sso-provisioning.d.ts +320 -0
  325. package/src/lib/server/sso-provisioning.js +715 -0
  326. package/src/lib/server/sso-provisioning.js.map +1 -0
  327. package/src/lib/server/staff-alert-email.d.ts +41 -0
  328. package/src/lib/server/staff-alert-email.js +63 -0
  329. package/src/lib/server/staff-alert-email.js.map +1 -0
  330. package/src/lib/server/stripe-account-mode.d.ts +156 -0
  331. package/src/lib/server/stripe-account-mode.js +162 -0
  332. package/src/lib/server/stripe-account-mode.js.map +1 -0
  333. package/src/lib/server/tenant-write-lockdown.d.ts +131 -0
  334. package/src/lib/server/tenant-write-lockdown.js +176 -0
  335. package/src/lib/server/tenant-write-lockdown.js.map +1 -0
  336. package/src/lib/server/test-firestore.d.ts +45 -0
  337. package/src/lib/server/test-firestore.js +124 -0
  338. package/src/lib/server/test-firestore.js.map +1 -0
  339. package/src/lib/server/token-revocation.d.ts +140 -0
  340. package/src/lib/server/token-revocation.js +255 -0
  341. package/src/lib/server/token-revocation.js.map +1 -0
  342. package/src/lib/server/update-existing.d.ts +32 -0
  343. package/src/lib/server/update-existing.js +73 -0
  344. package/src/lib/server/update-existing.js.map +1 -0
  345. package/src/lib/server/upload-cors-reconcile.d.ts +118 -0
  346. package/src/lib/server/upload-cors-reconcile.js +234 -0
  347. package/src/lib/server/upload-cors-reconcile.js.map +1 -0
  348. package/src/lib/server/upsert-contact.d.ts +262 -0
  349. package/src/lib/server/upsert-contact.js +546 -0
  350. package/src/lib/server/upsert-contact.js.map +1 -0
  351. package/src/lib/server/usage-invoice.d.ts +203 -0
  352. package/src/lib/server/usage-invoice.js +397 -0
  353. package/src/lib/server/usage-invoice.js.map +1 -0
  354. package/src/lib/server/user-profiles.d.ts +151 -0
  355. package/src/lib/server/user-profiles.js +364 -0
  356. package/src/lib/server/user-profiles.js.map +1 -0
  357. package/src/lib/server/vercel-drain-signature.d.ts +30 -0
  358. package/src/lib/server/vercel-drain-signature.js +61 -0
  359. package/src/lib/server/vercel-drain-signature.js.map +1 -0
  360. package/src/lib/server/vercel-log-drain.d.ts +259 -0
  361. package/src/lib/server/vercel-log-drain.js +479 -0
  362. package/src/lib/server/vercel-log-drain.js.map +1 -0
  363. package/src/lib/server/verify-email-cooldown.d.ts +102 -0
  364. package/src/lib/server/verify-email-cooldown.js +114 -0
  365. package/src/lib/server/verify-email-cooldown.js.map +1 -0
  366. package/src/lib/server/visitor-write-rate-limit.d.ts +87 -0
  367. package/src/lib/server/visitor-write-rate-limit.js +117 -0
  368. package/src/lib/server/visitor-write-rate-limit.js.map +1 -0
  369. package/src/lib/server/workspace-domains.d.ts +156 -0
  370. package/src/lib/server/workspace-domains.js +271 -0
  371. package/src/lib/server/workspace-domains.js.map +1 -0
  372. package/src/tenancy.d.ts +115 -0
  373. package/src/tenancy.js +142 -0
  374. package/src/tenancy.js.map +1 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Bulk uid → person resolution for staff surfaces (AGL-938).
19
+ *
20
+ * A staff page must never show a raw uid where a name or email will do
21
+ * (AGL-810), but "resolve the uid" is a three-store question:
22
+ *
23
+ * 1. **Firebase Auth pools** — the project pool plus every GCIP tenant, via
24
+ * `findUserByUidAcrossPools` (AGL-1122). A project-level lookup alone
25
+ * would silently miss every SSO account.
26
+ * 2. **The org member roster**, `orgs/{orgId}/members/{uid}` — the identity
27
+ * source for members whose auth record cannot be reached (a deleted
28
+ * account whose membership lingers, or a tenant-listing outage while the
29
+ * pools fail soft). The roster carries `email`/`displayName` precisely so
30
+ * other people stay nameable without an auth read (AGL-1127).
31
+ * 3. **Nobody** — `system:cron` actors, erased accounts. The uid comes back
32
+ * marked unresolved so the caller can render it as itself, with a hint,
33
+ * rather than crash or spin.
34
+ *
35
+ * Fail-soft by contract: an outage in any store degrades a name back to a
36
+ * uid. It must never take down the page that asked.
37
+ */
38
+ import type { PooledUserRecord } from './auth-pools';
39
+ /** Where a uid resolved: an auth pool, the org roster, or nowhere. */
40
+ export type PersonSource = 'auth' | 'roster';
41
+ export interface ResolvedPerson {
42
+ uid: string;
43
+ email: string | null;
44
+ displayName: string | null;
45
+ /** Null when no store answered — render the uid itself, flagged unknown. */
46
+ source: PersonSource | null;
47
+ }
48
+ export interface ResolveUidsOptions {
49
+ /**
50
+ * Org whose member roster backs up the auth pools. Without it, uids that
51
+ * miss every pool simply come back unresolved.
52
+ */
53
+ orgId?: string;
54
+ /** Injectable for tests; defaults to the admin app's Firestore. */
55
+ firestore?: any;
56
+ /** Injectable for tests; defaults to `findUserByUidAcrossPools`. */
57
+ findUser?: (uid: string) => Promise<PooledUserRecord | null>;
58
+ }
59
+ /**
60
+ * Resolve a batch of uids to people, deduplicated, keyed by uid. Every
61
+ * requested uid is present in the result — unresolvable ones as
62
+ * `{ email: null, displayName: null, source: null }` — so callers can index
63
+ * without existence checks.
64
+ */
65
+ export declare function resolveUidsToPeople(uids: ReadonlyArray<string | null | undefined>, options?: ResolveUidsOptions): Promise<Record<string, ResolvedPerson>>;
66
+ export default resolveUidsToPeople;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * Bulk uid → person resolution for staff surfaces (AGL-938).
18
+ *
19
+ * A staff page must never show a raw uid where a name or email will do
20
+ * (AGL-810), but "resolve the uid" is a three-store question:
21
+ *
22
+ * 1. **Firebase Auth pools** — the project pool plus every GCIP tenant, via
23
+ * `findUserByUidAcrossPools` (AGL-1122). A project-level lookup alone
24
+ * would silently miss every SSO account.
25
+ * 2. **The org member roster**, `orgs/{orgId}/members/{uid}` — the identity
26
+ * source for members whose auth record cannot be reached (a deleted
27
+ * account whose membership lingers, or a tenant-listing outage while the
28
+ * pools fail soft). The roster carries `email`/`displayName` precisely so
29
+ * other people stay nameable without an auth read (AGL-1127).
30
+ * 3. **Nobody** — `system:cron` actors, erased accounts. The uid comes back
31
+ * marked unresolved so the caller can render it as itself, with a hint,
32
+ * rather than crash or spin.
33
+ *
34
+ * Fail-soft by contract: an outage in any store degrades a name back to a
35
+ * uid. It must never take down the page that asked.
36
+ */ import { findUserByUidAcrossPools } from "./auth-pools.js";
37
+ import firebaseAdmin from "./firebase-admin.js";
38
+ /**
39
+ * Resolve a batch of uids to people, deduplicated, keyed by uid. Every
40
+ * requested uid is present in the result — unresolvable ones as
41
+ * `{ email: null, displayName: null, source: null }` — so callers can index
42
+ * without existence checks.
43
+ */ export async function resolveUidsToPeople(uids, options = {}) {
44
+ var _options_findUser;
45
+ const find = (_options_findUser = options.findUser) != null ? _options_findUser : findUserByUidAcrossPools;
46
+ const unique = [
47
+ ...new Set(uids.filter((uid)=>typeof uid === 'string' && !!uid))
48
+ ];
49
+ const people = {};
50
+ const missed = [];
51
+ await Promise.all(unique.map(async (uid)=>{
52
+ try {
53
+ const found = await find(uid);
54
+ if (found) {
55
+ var _found_record_email, _found_record_displayName;
56
+ people[uid] = {
57
+ uid,
58
+ email: (_found_record_email = found.record.email) != null ? _found_record_email : null,
59
+ displayName: (_found_record_displayName = found.record.displayName) != null ? _found_record_displayName : null,
60
+ source: 'auth'
61
+ };
62
+ return;
63
+ }
64
+ } catch (unused) {
65
+ // An auth outage is a miss, not a failure — the roster below may
66
+ // still name this person.
67
+ }
68
+ missed.push(uid);
69
+ }));
70
+ if (missed.length && options.orgId) {
71
+ try {
72
+ var _options_firestore;
73
+ const db = (_options_firestore = options.firestore) != null ? _options_firestore : firebaseAdmin.app().firestore();
74
+ const members = db.collection('orgs').doc(options.orgId).collection('members');
75
+ const snapshots = await db.getAll(...missed.map((uid)=>members.doc(uid)));
76
+ snapshots.forEach((snapshot, index)=>{
77
+ if (!snapshot.exists) return;
78
+ const email = snapshot.get('email');
79
+ const displayName = snapshot.get('displayName');
80
+ // A roster doc with neither field names nobody — that uid stays
81
+ // unresolved rather than resolving to an empty person.
82
+ if (typeof email !== 'string' && typeof displayName !== 'string') {
83
+ return;
84
+ }
85
+ people[missed[index]] = {
86
+ uid: missed[index],
87
+ email: typeof email === 'string' && email ? email : null,
88
+ displayName: typeof displayName === 'string' && displayName ? displayName : null,
89
+ source: 'roster'
90
+ };
91
+ });
92
+ } catch (error) {
93
+ // Roster unreachable: those uids render as themselves. Logged, not
94
+ // thrown — a labelling nicety must not 500 the page that asked.
95
+ console.error('roster fallback failed while resolving uids', error);
96
+ }
97
+ }
98
+ for (const uid of unique){
99
+ if (!people[uid]) {
100
+ people[uid] = {
101
+ uid,
102
+ email: null,
103
+ displayName: null,
104
+ source: null
105
+ };
106
+ }
107
+ }
108
+ return people;
109
+ }
110
+ export default resolveUidsToPeople;
111
+
112
+ //# sourceMappingURL=resolve-people.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/resolve-people.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Bulk uid → person resolution for staff surfaces (AGL-938).\n *\n * A staff page must never show a raw uid where a name or email will do\n * (AGL-810), but \"resolve the uid\" is a three-store question:\n *\n * 1. **Firebase Auth pools** — the project pool plus every GCIP tenant, via\n * `findUserByUidAcrossPools` (AGL-1122). A project-level lookup alone\n * would silently miss every SSO account.\n * 2. **The org member roster**, `orgs/{orgId}/members/{uid}` — the identity\n * source for members whose auth record cannot be reached (a deleted\n * account whose membership lingers, or a tenant-listing outage while the\n * pools fail soft). The roster carries `email`/`displayName` precisely so\n * other people stay nameable without an auth read (AGL-1127).\n * 3. **Nobody** — `system:cron` actors, erased accounts. The uid comes back\n * marked unresolved so the caller can render it as itself, with a hint,\n * rather than crash or spin.\n *\n * Fail-soft by contract: an outage in any store degrades a name back to a\n * uid. It must never take down the page that asked.\n */\n\nimport type { PooledUserRecord } from './auth-pools'\nimport { findUserByUidAcrossPools } from './auth-pools'\nimport firebaseAdmin from './firebase-admin'\n\n/** Where a uid resolved: an auth pool, the org roster, or nowhere. */\nexport type PersonSource = 'auth' | 'roster'\n\nexport interface ResolvedPerson {\n uid: string\n email: string | null\n displayName: string | null\n /** Null when no store answered — render the uid itself, flagged unknown. */\n source: PersonSource | null\n}\n\nexport interface ResolveUidsOptions {\n /**\n * Org whose member roster backs up the auth pools. Without it, uids that\n * miss every pool simply come back unresolved.\n */\n orgId?: string\n /** Injectable for tests; defaults to the admin app's Firestore. */\n firestore?: any\n /** Injectable for tests; defaults to `findUserByUidAcrossPools`. */\n findUser?: (uid: string) => Promise<PooledUserRecord | null>\n}\n\n/**\n * Resolve a batch of uids to people, deduplicated, keyed by uid. Every\n * requested uid is present in the result — unresolvable ones as\n * `{ email: null, displayName: null, source: null }` — so callers can index\n * without existence checks.\n */\nexport async function resolveUidsToPeople(\n uids: ReadonlyArray<string | null | undefined>,\n options: ResolveUidsOptions = {},\n): Promise<Record<string, ResolvedPerson>> {\n const find = options.findUser ?? findUserByUidAcrossPools\n const unique = [\n ...new Set(\n uids.filter((uid): uid is string => typeof uid === 'string' && !!uid),\n ),\n ]\n const people: Record<string, ResolvedPerson> = {}\n const missed: string[] = []\n\n await Promise.all(\n unique.map(async (uid) => {\n try {\n const found = await find(uid)\n if (found) {\n people[uid] = {\n uid,\n email: found.record.email ?? null,\n displayName: found.record.displayName ?? null,\n source: 'auth',\n }\n return\n }\n } catch {\n // An auth outage is a miss, not a failure — the roster below may\n // still name this person.\n }\n missed.push(uid)\n }),\n )\n\n if (missed.length && options.orgId) {\n try {\n const db = options.firestore ?? firebaseAdmin.app().firestore()\n const members = db\n .collection('orgs')\n .doc(options.orgId)\n .collection('members')\n const snapshots = await db.getAll(\n ...missed.map((uid: string) => members.doc(uid)),\n )\n snapshots.forEach((snapshot: any, index: number) => {\n if (!snapshot.exists) return\n const email = snapshot.get('email')\n const displayName = snapshot.get('displayName')\n // A roster doc with neither field names nobody — that uid stays\n // unresolved rather than resolving to an empty person.\n if (typeof email !== 'string' && typeof displayName !== 'string') {\n return\n }\n people[missed[index]] = {\n uid: missed[index],\n email: typeof email === 'string' && email ? email : null,\n displayName:\n typeof displayName === 'string' && displayName\n ? displayName\n : null,\n source: 'roster',\n }\n })\n } catch (error) {\n // Roster unreachable: those uids render as themselves. Logged, not\n // thrown — a labelling nicety must not 500 the page that asked.\n console.error('roster fallback failed while resolving uids', error)\n }\n }\n\n for (const uid of unique) {\n if (!people[uid]) {\n people[uid] = { uid, email: null, displayName: null, source: null }\n }\n }\n return people\n}\n\nexport default resolveUidsToPeople\n"],"names":["findUserByUidAcrossPools","firebaseAdmin","resolveUidsToPeople","uids","options","find","findUser","unique","Set","filter","uid","people","missed","Promise","all","map","found","email","record","displayName","source","push","length","orgId","db","firestore","app","members","collection","doc","snapshots","getAll","forEach","snapshot","index","exists","get","error","console"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;CAoBC,GAGD,SAASA,wBAAwB,QAAQ,kBAAc;AACvD,OAAOC,mBAAmB,sBAAkB;AAyB5C;;;;;CAKC,GACD,OAAO,eAAeC,oBACpBC,IAA8C,EAC9CC,UAA8B,CAAC,CAAC;QAEnBA;IAAb,MAAMC,QAAOD,oBAAAA,QAAQE,QAAQ,YAAhBF,oBAAoBJ;IACjC,MAAMO,SAAS;WACV,IAAIC,IACLL,KAAKM,MAAM,CAAC,CAACC,MAAuB,OAAOA,QAAQ,YAAY,CAAC,CAACA;KAEpE;IACD,MAAMC,SAAyC,CAAC;IAChD,MAAMC,SAAmB,EAAE;IAE3B,MAAMC,QAAQC,GAAG,CACfP,OAAOQ,GAAG,CAAC,OAAOL;QAChB,IAAI;YACF,MAAMM,QAAQ,MAAMX,KAAKK;YACzB,IAAIM,OAAO;oBAGAA,qBACMA;gBAHfL,MAAM,CAACD,IAAI,GAAG;oBACZA;oBACAO,KAAK,GAAED,sBAAAA,MAAME,MAAM,CAACD,KAAK,YAAlBD,sBAAsB;oBAC7BG,WAAW,GAAEH,4BAAAA,MAAME,MAAM,CAACC,WAAW,YAAxBH,4BAA4B;oBACzCI,QAAQ;gBACV;gBACA;YACF;QACF,EAAE,eAAM;QACN,iEAAiE;QACjE,0BAA0B;QAC5B;QACAR,OAAOS,IAAI,CAACX;IACd;IAGF,IAAIE,OAAOU,MAAM,IAAIlB,QAAQmB,KAAK,EAAE;QAClC,IAAI;gBACSnB;YAAX,MAAMoB,MAAKpB,qBAAAA,QAAQqB,SAAS,YAAjBrB,qBAAqBH,cAAcyB,GAAG,GAAGD,SAAS;YAC7D,MAAME,UAAUH,GACbI,UAAU,CAAC,QACXC,GAAG,CAACzB,QAAQmB,KAAK,EACjBK,UAAU,CAAC;YACd,MAAME,YAAY,MAAMN,GAAGO,MAAM,IAC5BnB,OAAOG,GAAG,CAAC,CAACL,MAAgBiB,QAAQE,GAAG,CAACnB;YAE7CoB,UAAUE,OAAO,CAAC,CAACC,UAAeC;gBAChC,IAAI,CAACD,SAASE,MAAM,EAAE;gBACtB,MAAMlB,QAAQgB,SAASG,GAAG,CAAC;gBAC3B,MAAMjB,cAAcc,SAASG,GAAG,CAAC;gBACjC,gEAAgE;gBAChE,uDAAuD;gBACvD,IAAI,OAAOnB,UAAU,YAAY,OAAOE,gBAAgB,UAAU;oBAChE;gBACF;gBACAR,MAAM,CAACC,MAAM,CAACsB,MAAM,CAAC,GAAG;oBACtBxB,KAAKE,MAAM,CAACsB,MAAM;oBAClBjB,OAAO,OAAOA,UAAU,YAAYA,QAAQA,QAAQ;oBACpDE,aACE,OAAOA,gBAAgB,YAAYA,cAC/BA,cACA;oBACNC,QAAQ;gBACV;YACF;QACF,EAAE,OAAOiB,OAAO;YACd,mEAAmE;YACnE,gEAAgE;YAChEC,QAAQD,KAAK,CAAC,+CAA+CA;QAC/D;IACF;IAEA,KAAK,MAAM3B,OAAOH,OAAQ;QACxB,IAAI,CAACI,MAAM,CAACD,IAAI,EAAE;YAChBC,MAAM,CAACD,IAAI,GAAG;gBAAEA;gBAAKO,OAAO;gBAAME,aAAa;gBAAMC,QAAQ;YAAK;QACpE;IACF;IACA,OAAOT;AACT;AAEA,eAAeT,oBAAmB"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Constant-time string comparison that tolerates a length mismatch
19
+ * (AGL-1353 D8, extraction 2).
20
+ *
21
+ * The length-check-then-`timingSafeEqual` dance was hand-written in six files:
22
+ * `media-signing.ts`, `edit-access-token.ts`, commerce `download.ts`,
23
+ * `membership.ts`, `workflows/server.ts` and `apps/console/utils/cron-auth.ts`.
24
+ * Every one of them carries its own note explaining the same hazard, which is
25
+ * the shape of a helper that has not been written yet.
26
+ *
27
+ * **The length check is the load-bearing half.** `timingSafeEqual` THROWS on
28
+ * buffers of different lengths, and in every one of those call sites the
29
+ * length is attacker-controlled — a presented signature, a token segment, a
30
+ * header. Forgetting it turns a `401`/`403` into an unhandled `500`, which is
31
+ * both an outage and an oracle: a thrown request and a refused one are
32
+ * distinguishable from outside.
33
+ *
34
+ * **What this does and does not hide.** The comparison itself is constant-time
35
+ * for equal-length inputs. The length is compared first and in variable time,
36
+ * so this leaks whether the candidate was the right LENGTH and nothing else —
37
+ * the same property every hand-written copy had, and an acceptable one when
38
+ * the expected length is a public constant (a hex digest, a base64url secret)
39
+ * rather than a secret.
40
+ *
41
+ * Byte length, not code points: both sides are encoded as UTF-8 before
42
+ * comparison, so a multi-byte candidate cannot slip past the length check and
43
+ * reach the throwing call.
44
+ */
45
+ export declare function safeEqual(presented: string | null | undefined, expected: string | null | undefined): boolean;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { timingSafeEqual } from "crypto";
17
+ /**
18
+ * Constant-time string comparison that tolerates a length mismatch
19
+ * (AGL-1353 D8, extraction 2).
20
+ *
21
+ * The length-check-then-`timingSafeEqual` dance was hand-written in six files:
22
+ * `media-signing.ts`, `edit-access-token.ts`, commerce `download.ts`,
23
+ * `membership.ts`, `workflows/server.ts` and `apps/console/utils/cron-auth.ts`.
24
+ * Every one of them carries its own note explaining the same hazard, which is
25
+ * the shape of a helper that has not been written yet.
26
+ *
27
+ * **The length check is the load-bearing half.** `timingSafeEqual` THROWS on
28
+ * buffers of different lengths, and in every one of those call sites the
29
+ * length is attacker-controlled — a presented signature, a token segment, a
30
+ * header. Forgetting it turns a `401`/`403` into an unhandled `500`, which is
31
+ * both an outage and an oracle: a thrown request and a refused one are
32
+ * distinguishable from outside.
33
+ *
34
+ * **What this does and does not hide.** The comparison itself is constant-time
35
+ * for equal-length inputs. The length is compared first and in variable time,
36
+ * so this leaks whether the candidate was the right LENGTH and nothing else —
37
+ * the same property every hand-written copy had, and an acceptable one when
38
+ * the expected length is a public constant (a hex digest, a base64url secret)
39
+ * rather than a secret.
40
+ *
41
+ * Byte length, not code points: both sides are encoded as UTF-8 before
42
+ * comparison, so a multi-byte candidate cannot slip past the length check and
43
+ * reach the throwing call.
44
+ */ export function safeEqual(presented, expected) {
45
+ if (typeof presented !== 'string' || typeof expected !== 'string') {
46
+ return false;
47
+ }
48
+ const a = Buffer.from(presented, 'utf8');
49
+ const b = Buffer.from(expected, 'utf8');
50
+ // Both empty is a match only in the vacuous sense, and every caller here is
51
+ // comparing against a value that must exist. An empty expectation means a
52
+ // secret was not configured, so refusing is the fail-closed answer.
53
+ if (a.length === 0 || b.length === 0) return false;
54
+ if (a.length !== b.length) return false;
55
+ return timingSafeEqual(new Uint8Array(a), new Uint8Array(b));
56
+ }
57
+
58
+ //# sourceMappingURL=safe-equal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/safe-equal.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { timingSafeEqual } from 'crypto'\n\n/**\n * Constant-time string comparison that tolerates a length mismatch\n * (AGL-1353 D8, extraction 2).\n *\n * The length-check-then-`timingSafeEqual` dance was hand-written in six files:\n * `media-signing.ts`, `edit-access-token.ts`, commerce `download.ts`,\n * `membership.ts`, `workflows/server.ts` and `apps/console/utils/cron-auth.ts`.\n * Every one of them carries its own note explaining the same hazard, which is\n * the shape of a helper that has not been written yet.\n *\n * **The length check is the load-bearing half.** `timingSafeEqual` THROWS on\n * buffers of different lengths, and in every one of those call sites the\n * length is attacker-controlled — a presented signature, a token segment, a\n * header. Forgetting it turns a `401`/`403` into an unhandled `500`, which is\n * both an outage and an oracle: a thrown request and a refused one are\n * distinguishable from outside.\n *\n * **What this does and does not hide.** The comparison itself is constant-time\n * for equal-length inputs. The length is compared first and in variable time,\n * so this leaks whether the candidate was the right LENGTH and nothing else —\n * the same property every hand-written copy had, and an acceptable one when\n * the expected length is a public constant (a hex digest, a base64url secret)\n * rather than a secret.\n *\n * Byte length, not code points: both sides are encoded as UTF-8 before\n * comparison, so a multi-byte candidate cannot slip past the length check and\n * reach the throwing call.\n */\nexport function safeEqual(\n presented: string | null | undefined,\n expected: string | null | undefined,\n): boolean {\n if (typeof presented !== 'string' || typeof expected !== 'string') {\n return false\n }\n const a = Buffer.from(presented, 'utf8')\n const b = Buffer.from(expected, 'utf8')\n // Both empty is a match only in the vacuous sense, and every caller here is\n // comparing against a value that must exist. An empty expectation means a\n // secret was not configured, so refusing is the fail-closed answer.\n if (a.length === 0 || b.length === 0) return false\n if (a.length !== b.length) return false\n return timingSafeEqual(new Uint8Array(a), new Uint8Array(b))\n}\n"],"names":["timingSafeEqual","safeEqual","presented","expected","a","Buffer","from","b","length","Uint8Array"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,eAAe,QAAQ,SAAQ;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,SAASC,UACdC,SAAoC,EACpCC,QAAmC;IAEnC,IAAI,OAAOD,cAAc,YAAY,OAAOC,aAAa,UAAU;QACjE,OAAO;IACT;IACA,MAAMC,IAAIC,OAAOC,IAAI,CAACJ,WAAW;IACjC,MAAMK,IAAIF,OAAOC,IAAI,CAACH,UAAU;IAChC,4EAA4E;IAC5E,0EAA0E;IAC1E,oEAAoE;IACpE,IAAIC,EAAEI,MAAM,KAAK,KAAKD,EAAEC,MAAM,KAAK,GAAG,OAAO;IAC7C,IAAIJ,EAAEI,MAAM,KAAKD,EAAEC,MAAM,EAAE,OAAO;IAClC,OAAOR,gBAAgB,IAAIS,WAAWL,IAAI,IAAIK,WAAWF;AAC3D"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { type HostSendingDomainTeardown } from './host-sending-domain';
18
+ /**
19
+ * The console-side teardown, injected rather than imported.
20
+ *
21
+ * Releasing the provider's domain object needs a full-access mail credential
22
+ * and removing the zone records needs a DNS token, and neither may be
23
+ * reachable from the tenant runtime — which is what makes them live in
24
+ * `apps/console` and makes this library structurally unable to import them
25
+ * (`sending-domain-credential-isolation.spec.ts` sweeps the tree for it).
26
+ *
27
+ * A caller that HAS those credentials passes the driver in and the domain is
28
+ * released inline. A caller that does not — the tenant runtime, an operator
29
+ * script, a self-host with no provider configured — records the debt and the
30
+ * console's reaper settles it. Both are correct; only the latency differs.
31
+ */
32
+ export type TeardownSendingDomainDriver = (teardown: HostSendingDomainTeardown) => Promise<{
33
+ outcome: 'removed' | 'skipped' | 'failed';
34
+ detail: string | null;
35
+ }>;
36
+ /** What became of one site's dedicated sending domain. */
37
+ export type SendingDomainDisposition =
38
+ /** The site had no dedicated domain of its own. Nothing to release. */
39
+ 'none'
40
+ /** Provider slot freed, zone records removed, our records dropped. */
41
+ | 'released'
42
+ /** The debt is recorded on the label claim; the reaper owes it a visit. */
43
+ | 'deferred'
44
+ /** A shared pool member. Never torn down, by anything, ever. */
45
+ | 'protected';
46
+ export interface SendingDomainDebtRecord {
47
+ /** The claimed label, and the id of the claim document. */
48
+ label: string;
49
+ hostId: string | null;
50
+ orgId: string | null;
51
+ domain: string | null;
52
+ claimedAtMs: number | null;
53
+ /** Set when a teardown could not be completed. Null on a healthy claim. */
54
+ orphanedAtMs: number | null;
55
+ /** A short code naming what refused, safe to store, log and show. */
56
+ teardownDetail: string | null;
57
+ /** How many passes have tried and failed to settle this. */
58
+ teardownAttempts: number;
59
+ providerDomainId: string | null;
60
+ dkimSelector: string | null;
61
+ }
62
+ /** One claim document as a debt record. */
63
+ export declare function readSendingDomainDebt(snapshot: FirebaseFirestore.DocumentSnapshot): SendingDomainDebtRecord | null;
64
+ /**
65
+ * Everything needed to release one PINNED label's domain, read by label.
66
+ *
67
+ * Keyed on the label and never on `hosts/{hostId}.sendingDomain`, and the
68
+ * difference is not cosmetic. That field is the site's CURRENT SELECTION and a
69
+ * site may point it at the org's own verified domain through the sending
70
+ * identity surface — a name this deployment did not provision, holds no
71
+ * provider slot for, and whose record belongs to the ORG and is shared with
72
+ * every other site of theirs. A teardown that read the selection would release
73
+ * an agency's verified domain because one of its sites was deleted.
74
+ *
75
+ * The label is the thing this deployment actually created, it is written once
76
+ * and never rewritten, and {@link platformSendingDomainFor} re-derives the
77
+ * domain from it under the current apex and the current reserved set.
78
+ *
79
+ * Works for a host that no longer exists: the claim carries the org, and the
80
+ * provider id and selector are copied onto the claim before an erasure
81
+ * destroys the record they came from.
82
+ */
83
+ export declare function readSendingDomainTeardownByLabel(label: string | null | undefined): Promise<HostSendingDomainTeardown | null>;
84
+ /**
85
+ * Copy the vendor handles onto the claim and mark the owner gone.
86
+ *
87
+ * Written with `merge` onto a document that already exists, so it adds the
88
+ * debt to the claim rather than replacing it — the `hostId` the claim carries
89
+ * is what `releaseHostSendingDomain` matches on before deleting it, and losing
90
+ * that would strand the claim permanently.
91
+ *
92
+ * `teardownAttempts` increments so a debt that cannot be settled — a provider
93
+ * that has forgotten the domain, a token that was never restored — is visible
94
+ * as a number climbing rather than as a row that looks the same every day.
95
+ */
96
+ export declare function recordSendingDomainDebt(teardown: HostSendingDomainTeardown, detail: string | null): Promise<void>;
97
+ /**
98
+ * Release one site's dedicated sending domain, or record what is still owed.
99
+ *
100
+ * The single entry point for every path that destroys a site. It never throws
101
+ * and it never blocks its caller on a vendor: the worst outcome is a debt on
102
+ * the label claim and a loud line naming the domain.
103
+ *
104
+ * Ordered provider → zone → our records by the driver it calls, for the reason
105
+ * stated there: the provider slot is the scarce resource, and our own record
106
+ * is what keeps a half-finished teardown findable.
107
+ */
108
+ export declare function disposeHostSendingDomain(options: {
109
+ /** The site being destroyed. Its `sendingLabel` is read before it goes. */
110
+ hostId?: string | null;
111
+ /** Pre-read teardown, for a caller that has already lost the host document. */
112
+ teardown?: HostSendingDomainTeardown | null;
113
+ tearDown?: TeardownSendingDomainDriver | null;
114
+ }): Promise<SendingDomainDisposition>;
115
+ /**
116
+ * Every label claim, oldest first, for the orphan sweep.
117
+ *
118
+ * Ordered by document id rather than by a field, and paged with a cursor. A
119
+ * `limit()` with no ordering returns an arbitrary but STABLE sample — the same
120
+ * handful every run — and ordering on `claimedAtMs` would silently DROP any
121
+ * claim written before that field existed, which for a reaper means an orphan
122
+ * it can never see. `__name__` is present on every document by definition.
123
+ */
124
+ export declare function listSendingLabelClaims(options: {
125
+ limit: number;
126
+ after?: string | null;
127
+ }): Promise<SendingDomainDebtRecord[]>;