@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,81 @@
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
+ export interface ConsoleApiRateLimitOptions {
18
+ /** Dispatcher path, e.g. `email/list-members-add`. Decides machine vs not. */
19
+ path: string;
20
+ /**
21
+ * The verified Firebase uid, or null when the request carried no bearer
22
+ * token or one that did not decode. The console dispatcher has already
23
+ * decoded it for the lockdown gate, so this costs no second verification.
24
+ */
25
+ uid: string | null;
26
+ /** Read for its method and its client-address headers. */
27
+ request: {
28
+ method?: string;
29
+ headers?: {
30
+ get?: (name: string) => unknown;
31
+ };
32
+ };
33
+ limit?: number;
34
+ windowMs?: number;
35
+ nowMs?: number;
36
+ /** Injectable for tests; defaults to the Admin SDK's Firestore. */
37
+ firestore?: unknown;
38
+ }
39
+ /**
40
+ * Counts one console write and returns a 429 once the window is spent.
41
+ *
42
+ * ## Reads are not limited
43
+ *
44
+ * The standing rule in `RATE_LIMITING.md` is "`checkRateLimit` for volume,
45
+ * `consumeRateLimit` for consequence": a durable call costs one Firestore read
46
+ * plus one write, which is the right price beside a handler that installs a
47
+ * bundle or calls a paid model, and the wrong price in front of a listing GET.
48
+ * Every route on this surface that spends something spends it on a POST — the
49
+ * two email list previews, the member add, the suppression writes, `ai/assist`,
50
+ * every marketplace install and publish — so writes-only covers the exposure
51
+ * rather than merely most of it.
52
+ *
53
+ * ## Fail SOFT, inherited from `consumeRateLimit`
54
+ *
55
+ * A Firestore outage lets traffic through, flagged `degraded`, rather than
56
+ * refusing it; a contended key is refused. That classification is the store's
57
+ * and is not re-decided here. Failing closed would take the console's write
58
+ * surface down during an unrelated blip — the operator's own recovery tools
59
+ * among them — to bound spend that the outage has already stopped, since the
60
+ * counter and the documents these handlers write are one Firestore. CSRF fails
61
+ * closed because forging a request is the threat; here the threat is volume,
62
+ * and volume during an outage is not the incident.
63
+ *
64
+ * ## No staff bypass
65
+ *
66
+ * The lockdown gates above this one grant staff a bypass, because their
67
+ * question is "should anyone be doing this right now" and staff are how an
68
+ * incident gets diagnosed. This one's question is "how much is this costing",
69
+ * and a staff session spends exactly what a customer session spends. A bypass
70
+ * would also make the surface unlimited for the accounts most likely to be
71
+ * driving it from a script.
72
+ *
73
+ * ## What the caller is told
74
+ *
75
+ * A bare 429 with `Retry-After`, following `visitorWriteRateLimitRefusal` and
76
+ * `forms/submit`. The fallback bucket below is reached by callers that proved
77
+ * nothing, so the response says nothing a caller could spend the rest of the
78
+ * window on.
79
+ */
80
+ export declare function consoleApiRateLimitRefusal(options: ConsoleApiRateLimitOptions): Promise<Response | null>;
81
+ export default consoleApiRateLimitRefusal;
@@ -0,0 +1,111 @@
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 { CONSOLE_API_RATE_LIMIT, CONSOLE_API_RATE_WINDOW_MS, consoleApiRateLimitKey, isMachinePluginApiPath, lockdownIntentForMethod } from "@aglyn/aglyn/server";
17
+ import { consumeRateLimit } from "./rate-limit-store.js";
18
+ import { NO_CLIENT_ADDRESS_BUCKET, readClientIp } from "@aglyn/aglyn/app-utils/request-ip";
19
+ /**
20
+ * The rate-limit refusal a console plugin-API write returns, or null to
21
+ * proceed:
22
+ *
23
+ * const limited = await consoleApiRateLimitRefusal({ path, uid, request })
24
+ * if (limited) return limited
25
+ *
26
+ * The same split as `visitorWriteRateLimitRefusal` beside it — the policy
27
+ * (ceiling, window, key, which paths are exempt) is pure and lives in
28
+ * `@aglyn/aglyn/server`; this is only the durable half, which needs Firestore.
29
+ * The counter is `consumeRateLimit`, unchanged and unwrapped, so the console
30
+ * inherits its postures rather than acquiring a second set.
31
+ */ /**
32
+ * The caller's address, through the shared reader, or the no-address bucket.
33
+ *
34
+ * `readClientIp` counts from the RIGHT of the forwarding chain and is the only
35
+ * reader allowed to answer this question, so a caller cannot choose its own
36
+ * bucket by prepending an address.
37
+ */ function clientIp(request) {
38
+ var _readClientIp;
39
+ const headers = request == null ? void 0 : request.headers;
40
+ if (typeof (headers == null ? void 0 : headers.get) !== 'function') return NO_CLIENT_ADDRESS_BUCKET;
41
+ return (_readClientIp = readClientIp(headers)) != null ? _readClientIp : NO_CLIENT_ADDRESS_BUCKET;
42
+ }
43
+ /**
44
+ * Counts one console write and returns a 429 once the window is spent.
45
+ *
46
+ * ## Reads are not limited
47
+ *
48
+ * The standing rule in `RATE_LIMITING.md` is "`checkRateLimit` for volume,
49
+ * `consumeRateLimit` for consequence": a durable call costs one Firestore read
50
+ * plus one write, which is the right price beside a handler that installs a
51
+ * bundle or calls a paid model, and the wrong price in front of a listing GET.
52
+ * Every route on this surface that spends something spends it on a POST — the
53
+ * two email list previews, the member add, the suppression writes, `ai/assist`,
54
+ * every marketplace install and publish — so writes-only covers the exposure
55
+ * rather than merely most of it.
56
+ *
57
+ * ## Fail SOFT, inherited from `consumeRateLimit`
58
+ *
59
+ * A Firestore outage lets traffic through, flagged `degraded`, rather than
60
+ * refusing it; a contended key is refused. That classification is the store's
61
+ * and is not re-decided here. Failing closed would take the console's write
62
+ * surface down during an unrelated blip — the operator's own recovery tools
63
+ * among them — to bound spend that the outage has already stopped, since the
64
+ * counter and the documents these handlers write are one Firestore. CSRF fails
65
+ * closed because forging a request is the threat; here the threat is volume,
66
+ * and volume during an outage is not the incident.
67
+ *
68
+ * ## No staff bypass
69
+ *
70
+ * The lockdown gates above this one grant staff a bypass, because their
71
+ * question is "should anyone be doing this right now" and staff are how an
72
+ * incident gets diagnosed. This one's question is "how much is this costing",
73
+ * and a staff session spends exactly what a customer session spends. A bypass
74
+ * would also make the surface unlimited for the accounts most likely to be
75
+ * driving it from a script.
76
+ *
77
+ * ## What the caller is told
78
+ *
79
+ * A bare 429 with `Retry-After`, following `visitorWriteRateLimitRefusal` and
80
+ * `forms/submit`. The fallback bucket below is reached by callers that proved
81
+ * nothing, so the response says nothing a caller could spend the rest of the
82
+ * window on.
83
+ */ export async function consoleApiRateLimitRefusal(options) {
84
+ var _options_nowMs, _options_limit, _options_windowMs;
85
+ var _options_request;
86
+ if (lockdownIntentForMethod((_options_request = options.request) == null ? void 0 : _options_request.method) === 'read') return null;
87
+ if (isMachinePluginApiPath(options.path)) return null;
88
+ const nowMs = (_options_nowMs = options.nowMs) != null ? _options_nowMs : Date.now();
89
+ // Prefixed, so an address can never collide with a uid: Firebase uids are
90
+ // opaque and a bucket shared between an identified operator and everyone
91
+ // arriving from one address would refuse the wrong one of them.
92
+ const subject = options.uid ? `uid:${options.uid}` : `ip:${clientIp(options.request)}`;
93
+ const rate = await consumeRateLimit(consoleApiRateLimitKey(subject), {
94
+ limit: (_options_limit = options.limit) != null ? _options_limit : CONSOLE_API_RATE_LIMIT,
95
+ windowMs: (_options_windowMs = options.windowMs) != null ? _options_windowMs : CONSOLE_API_RATE_WINDOW_MS,
96
+ now: nowMs,
97
+ firestore: options.firestore
98
+ });
99
+ if (rate.allowed) return null;
100
+ return Response.json({
101
+ error: 'Too many requests'
102
+ }, {
103
+ status: 429,
104
+ headers: {
105
+ 'Retry-After': String(Math.max(1, Math.ceil((rate.resetMs - nowMs) / 1000)))
106
+ }
107
+ });
108
+ }
109
+ export default consoleApiRateLimitRefusal;
110
+
111
+ //# sourceMappingURL=console-api-rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/console-api-rate-limit.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 {\n CONSOLE_API_RATE_LIMIT,\n CONSOLE_API_RATE_WINDOW_MS,\n consoleApiRateLimitKey,\n isMachinePluginApiPath,\n lockdownIntentForMethod,\n} from '@aglyn/aglyn/server'\nimport { consumeRateLimit } from './rate-limit-store'\nimport {\n NO_CLIENT_ADDRESS_BUCKET,\n readClientIp,\n} from '@aglyn/aglyn/app-utils/request-ip'\n\n/**\n * The rate-limit refusal a console plugin-API write returns, or null to\n * proceed:\n *\n * const limited = await consoleApiRateLimitRefusal({ path, uid, request })\n * if (limited) return limited\n *\n * The same split as `visitorWriteRateLimitRefusal` beside it — the policy\n * (ceiling, window, key, which paths are exempt) is pure and lives in\n * `@aglyn/aglyn/server`; this is only the durable half, which needs Firestore.\n * The counter is `consumeRateLimit`, unchanged and unwrapped, so the console\n * inherits its postures rather than acquiring a second set.\n */\n\n/**\n * The caller's address, through the shared reader, or the no-address bucket.\n *\n * `readClientIp` counts from the RIGHT of the forwarding chain and is the only\n * reader allowed to answer this question, so a caller cannot choose its own\n * bucket by prepending an address.\n */\nfunction clientIp(request: {\n headers?: { get?: (name: string) => unknown }\n}): string {\n const headers = request?.headers\n if (typeof headers?.get !== 'function') return NO_CLIENT_ADDRESS_BUCKET\n return (\n readClientIp(headers as { get(name: string): string | null }) ??\n NO_CLIENT_ADDRESS_BUCKET\n )\n}\n\nexport interface ConsoleApiRateLimitOptions {\n /** Dispatcher path, e.g. `email/list-members-add`. Decides machine vs not. */\n path: string\n /**\n * The verified Firebase uid, or null when the request carried no bearer\n * token or one that did not decode. The console dispatcher has already\n * decoded it for the lockdown gate, so this costs no second verification.\n */\n uid: string | null\n /** Read for its method and its client-address headers. */\n request: { method?: string; headers?: { get?: (name: string) => unknown } }\n limit?: number\n windowMs?: number\n nowMs?: number\n /** Injectable for tests; defaults to the Admin SDK's Firestore. */\n firestore?: unknown\n}\n\n/**\n * Counts one console write and returns a 429 once the window is spent.\n *\n * ## Reads are not limited\n *\n * The standing rule in `RATE_LIMITING.md` is \"`checkRateLimit` for volume,\n * `consumeRateLimit` for consequence\": a durable call costs one Firestore read\n * plus one write, which is the right price beside a handler that installs a\n * bundle or calls a paid model, and the wrong price in front of a listing GET.\n * Every route on this surface that spends something spends it on a POST — the\n * two email list previews, the member add, the suppression writes, `ai/assist`,\n * every marketplace install and publish — so writes-only covers the exposure\n * rather than merely most of it.\n *\n * ## Fail SOFT, inherited from `consumeRateLimit`\n *\n * A Firestore outage lets traffic through, flagged `degraded`, rather than\n * refusing it; a contended key is refused. That classification is the store's\n * and is not re-decided here. Failing closed would take the console's write\n * surface down during an unrelated blip — the operator's own recovery tools\n * among them — to bound spend that the outage has already stopped, since the\n * counter and the documents these handlers write are one Firestore. CSRF fails\n * closed because forging a request is the threat; here the threat is volume,\n * and volume during an outage is not the incident.\n *\n * ## No staff bypass\n *\n * The lockdown gates above this one grant staff a bypass, because their\n * question is \"should anyone be doing this right now\" and staff are how an\n * incident gets diagnosed. This one's question is \"how much is this costing\",\n * and a staff session spends exactly what a customer session spends. A bypass\n * would also make the surface unlimited for the accounts most likely to be\n * driving it from a script.\n *\n * ## What the caller is told\n *\n * A bare 429 with `Retry-After`, following `visitorWriteRateLimitRefusal` and\n * `forms/submit`. The fallback bucket below is reached by callers that proved\n * nothing, so the response says nothing a caller could spend the rest of the\n * window on.\n */\nexport async function consoleApiRateLimitRefusal(\n options: ConsoleApiRateLimitOptions,\n): Promise<Response | null> {\n if (lockdownIntentForMethod(options.request?.method) === 'read') return null\n if (isMachinePluginApiPath(options.path)) return null\n\n const nowMs = options.nowMs ?? Date.now()\n // Prefixed, so an address can never collide with a uid: Firebase uids are\n // opaque and a bucket shared between an identified operator and everyone\n // arriving from one address would refuse the wrong one of them.\n const subject = options.uid\n ? `uid:${options.uid}`\n : `ip:${clientIp(options.request)}`\n const rate = await consumeRateLimit(consoleApiRateLimitKey(subject), {\n limit: options.limit ?? CONSOLE_API_RATE_LIMIT,\n windowMs: options.windowMs ?? CONSOLE_API_RATE_WINDOW_MS,\n now: nowMs,\n firestore: options.firestore,\n })\n if (rate.allowed) return null\n\n return Response.json(\n { error: 'Too many requests' },\n {\n status: 429,\n headers: {\n 'Retry-After': String(\n Math.max(1, Math.ceil((rate.resetMs - nowMs) / 1000)),\n ),\n },\n },\n )\n}\n\nexport default consoleApiRateLimitRefusal\n"],"names":["CONSOLE_API_RATE_LIMIT","CONSOLE_API_RATE_WINDOW_MS","consoleApiRateLimitKey","isMachinePluginApiPath","lockdownIntentForMethod","consumeRateLimit","NO_CLIENT_ADDRESS_BUCKET","readClientIp","clientIp","request","headers","get","consoleApiRateLimitRefusal","options","method","path","nowMs","Date","now","subject","uid","rate","limit","windowMs","firestore","allowed","Response","json","error","status","String","Math","max","ceil","resetMs"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,sBAAsB,EACtBC,0BAA0B,EAC1BC,sBAAsB,EACtBC,sBAAsB,EACtBC,uBAAuB,QAClB,sBAAqB;AAC5B,SAASC,gBAAgB,QAAQ,wBAAoB;AACrD,SACEC,wBAAwB,EACxBC,YAAY,QACP,oCAAmC;AAE1C;;;;;;;;;;;;CAYC,GAED;;;;;;CAMC,GACD,SAASC,SAASC,OAEjB;QAIGF;IAHF,MAAMG,UAAUD,2BAAAA,QAASC,OAAO;IAChC,IAAI,QAAOA,2BAAAA,QAASC,GAAG,MAAK,YAAY,OAAOL;IAC/C,QACEC,gBAAAA,aAAaG,oBAAbH,gBACAD;AAEJ;AAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCC,GACD,OAAO,eAAeM,2BACpBC,OAAmC;QAKrBA,gBAQLA,gBACGA;QAZgBA;IAA5B,IAAIT,yBAAwBS,mBAAAA,QAAQJ,OAAO,qBAAfI,iBAAiBC,MAAM,MAAM,QAAQ,OAAO;IACxE,IAAIX,uBAAuBU,QAAQE,IAAI,GAAG,OAAO;IAEjD,MAAMC,SAAQH,iBAAAA,QAAQG,KAAK,YAAbH,iBAAiBI,KAAKC,GAAG;IACvC,0EAA0E;IAC1E,yEAAyE;IACzE,gEAAgE;IAChE,MAAMC,UAAUN,QAAQO,GAAG,GACvB,CAAC,IAAI,EAAEP,QAAQO,GAAG,EAAE,GACpB,CAAC,GAAG,EAAEZ,SAASK,QAAQJ,OAAO,GAAG;IACrC,MAAMY,OAAO,MAAMhB,iBAAiBH,uBAAuBiB,UAAU;QACnEG,KAAK,GAAET,iBAAAA,QAAQS,KAAK,YAAbT,iBAAiBb;QACxBuB,QAAQ,GAAEV,oBAAAA,QAAQU,QAAQ,YAAhBV,oBAAoBZ;QAC9BiB,KAAKF;QACLQ,WAAWX,QAAQW,SAAS;IAC9B;IACA,IAAIH,KAAKI,OAAO,EAAE,OAAO;IAEzB,OAAOC,SAASC,IAAI,CAClB;QAAEC,OAAO;IAAoB,GAC7B;QACEC,QAAQ;QACRnB,SAAS;YACP,eAAeoB,OACbC,KAAKC,GAAG,CAAC,GAAGD,KAAKE,IAAI,CAAC,AAACZ,CAAAA,KAAKa,OAAO,GAAGlB,KAAI,IAAK;QAEnD;IACF;AAEJ;AAEA,eAAeJ,2BAA0B"}
@@ -0,0 +1,326 @@
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 DomainCheck } from './sso-provisioning';
18
+ import { type RecaptchaAllowlistResult } from './recaptcha-allowlist';
19
+ import { type WorkspaceDomainResult } from './workspace-domains';
20
+ import { normalizePlatformDomain } from './platform-domain-names';
21
+ /** Collection name, kept in one place so the rules file and this agree. */
22
+ export declare const CONSOLE_DOMAINS_COLLECTION = "consoleDomains";
23
+ /**
24
+ * Trim, lowercase, drop a trailing root dot, and tolerate a pasted URL.
25
+ *
26
+ * The console-flavoured name for the shared normaliser, kept because callers
27
+ * and the docs use it.
28
+ */
29
+ export declare const normalizeConsoleDomain: typeof normalizePlatformDomain;
30
+ /**
31
+ * Shape, length and reserved-name check.
32
+ *
33
+ * The RULES moved to `platform-domain-names.ts` (AGL-1430) so the site
34
+ * custom-domain path could stop being the only surface without them — it was
35
+ * the one with the live hole. Only the wording stays here: these two strings
36
+ * are what a customer reads in the console-domain wizard.
37
+ *
38
+ * `{ domain, error }` with both keys always present rather than a discriminated
39
+ * union, matching `validateSsoDomain` — `strictNullChecks` is off repo-wide and
40
+ * an `{ ok: true } | { ok: false }` union does not narrow reliably once it
41
+ * crosses a library boundary.
42
+ */
43
+ export declare function validateConsoleDomain(input: string): DomainCheck;
44
+ /**
45
+ * Every name this claim covers: the primary, then its twins.
46
+ *
47
+ * **A twin is a name we attach to Vercel that is not the one the customer
48
+ * asked for**, and it is the sharp edge of the whole file. Attaching
49
+ * `acme.com` without also attaching `www.acme.com` leaves half the traffic on
50
+ * the floor; attaching `www.acme.com` without *claiming* it leaves a name in
51
+ * our Vercel project that no Firestore document accounts for — and then a
52
+ * second org claims it, `attachProjectDomain` answers `already-exists`, and
53
+ * that org's visitors are redirected to the first org's console. The name is
54
+ * therefore derived here, claimed here, and attached from the same list.
55
+ *
56
+ * The apex test is deliberately narrow: exactly two labels. `acme.co.uk` is
57
+ * also an apex and gets no twin, which costs a customer a `www` redirect they
58
+ * can ask for by hand. Guessing wrong in the other direction — treating
59
+ * `console.acme.com` as an apex and quietly reserving `www.console.acme.com` —
60
+ * would reserve names on an org's behalf that it never asked for, and a
61
+ * reservation is the thing that locks another org out.
62
+ */
63
+ export declare function consoleDomainNames(domain: string): string[];
64
+ export type ConsoleDomainStatus = 'pending' | 'verified' | 'active' | 'suspended';
65
+ export interface ConsoleDomainClaimView {
66
+ domain: string;
67
+ orgId: string;
68
+ status: ConsoleDomainStatus;
69
+ token: string;
70
+ /** Every name the claim reserves — primary first. */
71
+ names: string[];
72
+ /** Fully-qualified host the TXT record goes on. */
73
+ recordHost: string;
74
+ /** Exact value the TXT record must carry. */
75
+ recordValue: string;
76
+ verified: boolean;
77
+ lastRecords?: string[];
78
+ }
79
+ /** Both keys always present, one always null — see `validateConsoleDomain`. */
80
+ export interface ConsoleDomainResult {
81
+ claim: ConsoleDomainClaimView | null;
82
+ error: string | null;
83
+ /** HTTP status a route should return. 200 whenever `claim` is set. */
84
+ status: number;
85
+ }
86
+ export declare class ConsoleDomainTakenError extends Error {
87
+ readonly domain: string;
88
+ constructor(domain: string);
89
+ }
90
+ /**
91
+ * Claim the primary and every twin in ONE transaction, or none of them.
92
+ *
93
+ * Modelled on the `orgSlugs` reservation in `organizations.ts`: read inside the
94
+ * transaction, refuse if someone else holds it, write in the same transaction.
95
+ * Every name is read with a single `getAll` so the whole set is covered by one
96
+ * transaction's read-set — claiming a twin in a follow-up write is precisely
97
+ * the AGL-743 hole this exists to close.
98
+ *
99
+ * Idempotent for the owning org, and it **keeps the existing token**: reissuing
100
+ * would invalidate a TXT record the customer may already have published and
101
+ * turn a working setup into a mysterious failure (the same reasoning as
102
+ * `issueDomainClaim`).
103
+ *
104
+ * Throws `ConsoleDomainTakenError` when any name in the set belongs to another
105
+ * org. Exported for the integration test, which needs to drive the transaction
106
+ * under real contention.
107
+ */
108
+ export declare function claimConsoleDomain(orgId: string, domain: string): Promise<ConsoleDomainClaimView>;
109
+ /**
110
+ * Start (or re-read) a registration: entitlement, validation, then the claim.
111
+ *
112
+ * The order matters. An org without `whiteLabel` must not be able to learn
113
+ * whether a domain is free, and must not leave a `pending` claim behind that
114
+ * blocks the org that *is* entitled to it.
115
+ */
116
+ export declare function registerConsoleDomain(options: {
117
+ orgId: string;
118
+ domain: string;
119
+ }): Promise<ConsoleDomainResult>;
120
+ /**
121
+ * Re-read DNS and record the verdict.
122
+ *
123
+ * Re-reads the claim first and refuses if the caller does not own it — the
124
+ * `publishSsoDomains` discipline, where nothing reaches the collection sign-in
125
+ * consults until a fresh lookup has seen the record. The comparison itself is
126
+ * `recordsProveOwnership`, an exact match on a whole TXT record: a substring
127
+ * test would accept `aglyn-domain-verification=<token>-and-more`, and a prefix
128
+ * test would accept anything that merely starts the same way.
129
+ */
130
+ export declare function verifyConsoleDomain(options: {
131
+ orgId: string;
132
+ domain: string;
133
+ }): Promise<ConsoleDomainResult>;
134
+ export interface ConsoleDomainAttachment {
135
+ domain: string;
136
+ results: WorkspaceDomainResult[];
137
+ /** Vercel's verdict alone: every claimed name is on the console project. */
138
+ attached: boolean;
139
+ /**
140
+ * Attached **and** able to attest — the only thing a caller may treat as
141
+ * "the customer can use this domain". `attached && !ready` is a real and
142
+ * reachable state: Vercel serves the name, App Check refuses it.
143
+ */
144
+ ready: boolean;
145
+ /**
146
+ * Non-null when a name this claim SERVES on cannot complete a large upload
147
+ * (AGL-1452), carrying the exact ordered command that fixes it.
148
+ *
149
+ * The attach itself still succeeds — the console does serve on the name, and
150
+ * refusing the domain over the upload path would be the worse outcome. But
151
+ * the customer's video, PDF and ZIP uploads will fail behind a generic "try
152
+ * again" snackbar until this is cleared, and the whole point of surfacing it
153
+ * here is that it stops being something a person has to remember: GCS
154
+ * matches CORS origins EXACTLY, so a new console origin needs its own entry
155
+ * and nothing about the eventual symptom points at bucket configuration.
156
+ *
157
+ * `attachProjectDomain` tries to add the entry itself; this is what is left
158
+ * when it could not — in practice, a runtime service account without
159
+ * `storage.buckets.update`.
160
+ */
161
+ uploadCorsRemedy: string | null;
162
+ /**
163
+ * The App Check reCAPTCHA allowlist write for the SERVING name (AGL-1378).
164
+ *
165
+ * Unlike `uploadCorsRemedy` this is **not** advisory. A console origin the
166
+ * key has never heard of cannot solve reCAPTCHA, so `getToken` fails with
167
+ * `appCheck/recaptcha-error` and Identity Platform refuses the first
168
+ * `signInWithCustomToken` with `401 UNAUTHENTICATED` — before it looks at
169
+ * the token. The domain would serve a console that renders and can never
170
+ * sign anyone in, and the customer-visible symptom is "Missing or
171
+ * insufficient permissions", indistinguishable from a rules verdict.
172
+ *
173
+ * So this participates in `attached`: a claim does not reach `active` unless
174
+ * `allowlistSatisfied()` says the origin can attest.
175
+ */
176
+ allowlist: RecaptchaAllowlistResult;
177
+ }
178
+ /**
179
+ * Attach every claimed name to the console Vercel project.
180
+ *
181
+ * ⚠️ Not called from anywhere. It exists so the mechanism is complete and
182
+ * tested; wiring it to a route is 1099c's job and must not happen before 1099d
183
+ * (see the header).
184
+ *
185
+ * Refuses unless the claim is this org's **and** currently verified, and unless
186
+ * the org still passes `whiteLabel`. The names come from the stored claim, not
187
+ * from `consoleDomainNames`, so a change to the twin rule can never attach a
188
+ * name the transaction did not reserve.
189
+ *
190
+ * Twins are registered as per-domain **redirects to the primary**, and the
191
+ * redirect value is a **bare hostname** — `attachProjectDomain` enforces that,
192
+ * because `https://${target}` is rejected by Vercel with a message that blames
193
+ * the target for being absent rather than the format (AGL-1365).
194
+ */
195
+ export declare function activateConsoleDomain(options: {
196
+ orgId: string;
197
+ domain: string;
198
+ }): Promise<ConsoleDomainResult & {
199
+ attachment: ConsoleDomainAttachment | null;
200
+ }>;
201
+ /**
202
+ * Kill the sessions, detach every name, then drop the claim — in that order.
203
+ *
204
+ * **The epoch bump comes first, and that is D7's own ordering**: *"`sessionEpoch
205
+ * = now` first, then Vercel `DELETE`, then delete the doc. Order matters: kill
206
+ * the sessions while we still control the host."* It was the one step of that
207
+ * sentence this function never performed, while
208
+ * {@link consoleSessionEpochRefuses} documented it as something release
209
+ * already did.
210
+ *
211
+ * Two things went wrong without it, and neither is covered by the Vercel
212
+ * detach:
213
+ *
214
+ * - **The in-flight window.** Vercel's `DELETE` and the allowlist reclaim are
215
+ * network round trips. Across all of them the claim still reads `active`, so
216
+ * `resolveConsoleDomain` says `servable` and `redeemConsoleHandoff` — which
217
+ * sits on `/api/*`, outside the middleware matcher — happily cashes an
218
+ * authorized handoff into a brand-new session on a domain we are in the
219
+ * middle of giving up.
220
+ * - **And that session then outlives the release entirely**, because the
221
+ * document carrying the epoch is deleted a moment later and
222
+ * `readConsoleSessionEpoch` reads a missing document as `0`, which every
223
+ * caller treats as "this control has nothing to say" and FAILS OPEN. The
224
+ * effect was that `suspendOnDowngrade` — the *lesser* action — revoked
225
+ * sessions properly while an explicit release did not revoke them at all.
226
+ *
227
+ * Bumping first inverts that: an authorization that predates the bump is
228
+ * refused `revoked` at redemption, so the window closes rather than merely
229
+ * being short. What survives the release is still only Vercel's allowlist,
230
+ * which is the boundary; this is the defence in depth behind it that D7 asked
231
+ * for and the code had stopped providing.
232
+ *
233
+ * Vercel before the documents, though, for the reason the header gives: a claim
234
+ * released while the name is still on the project is the unindexed-name hole,
235
+ * opened deliberately. If a detach fails the claim is kept and the caller is
236
+ * told, so the name stays reserved to the org that still holds it in Vercel —
237
+ * and the epoch bump is exactly the right residue on that path too, since
238
+ * sessions on a domain we just tried to release should not survive the attempt.
239
+ */
240
+ export declare function releaseConsoleDomain(options: {
241
+ orgId: string;
242
+ domain: string;
243
+ }): Promise<{
244
+ released: boolean;
245
+ results: WorkspaceDomainResult[];
246
+ /** Present once the reclaim was attempted — absent when Vercel refused first. */
247
+ allowlist?: RecaptchaAllowlistResult;
248
+ error: string | null;
249
+ }>;
250
+ /**
251
+ * Drop a claim that was never attached, without touching Vercel.
252
+ *
253
+ * The counterpart to claiming from the branding form: an org that clears or
254
+ * changes `customConsoleDomain` must not leave its old reservation standing,
255
+ * or it locks another org out of a name nobody is using. Deliberately refuses
256
+ * once the claim has proved ownership or reached Vercel — releasing *that*
257
+ * needs `releaseConsoleDomain`, because a claim dropped while the name is
258
+ * still on the project is the unindexed-name hole in the header.
259
+ */
260
+ export declare function releasePendingConsoleDomain(options: {
261
+ orgId: string;
262
+ domain: string;
263
+ }): Promise<boolean>;
264
+ /**
265
+ * Why a host may — or may not — be served the console (AGL-1099c).
266
+ *
267
+ * `reason` is not decoration. `unknown` and `degraded` both mean "serve it,
268
+ * this gate has no opinion", and they mean it for opposite causes; every other
269
+ * value means "refuse". Collapsing them into a boolean is how a lookup outage
270
+ * would come to read the same as a revoked entitlement.
271
+ */
272
+ export type ConsoleDomainReason = 'active' | 'unknown' | 'no-org' | 'not-entitled' | 'not-active' | 'degraded';
273
+ export interface ConsoleDomainVerdict {
274
+ /** A claim exists for this exact host. */
275
+ known: boolean;
276
+ /** The console may be served here, pinned to `orgSlug`. */
277
+ servable: boolean;
278
+ /**
279
+ * Workspace slug of the owning org — where a refused visitor is sent, and
280
+ * the org the path is rewritten under when servable. Never the `orgId`: a
281
+ * verdict is read by an unauthenticated route.
282
+ */
283
+ orgSlug: string | null;
284
+ reason: ConsoleDomainReason;
285
+ /** The lookup could not be completed. Honour it, never cache it. */
286
+ degraded: boolean;
287
+ }
288
+ /**
289
+ * Host → org, for the middleware gate and the session-route boundary.
290
+ *
291
+ * **One host pins exactly one org.** That is enforced by the document being
292
+ * keyed on the host and claimed transactionally (see the header), not by
293
+ * anything here — this function only ever reads the pin, and there is no input
294
+ * by which a caller can ask for a different org.
295
+ *
296
+ * The three "serve it anyway" answers, and why each is right:
297
+ *
298
+ * - **`unknown`** — no claim on this host. localhost, preview deployments and
299
+ * self-hosted installs all land here, and they must keep working. It is safe
300
+ * because of the detach ordering `releaseConsoleDomain` enforces: Vercel
301
+ * first, documents second, and the claim is kept if the detach fails. So a
302
+ * name the console project still answers for always has a document, and a
303
+ * name with no document cannot reach this deployment through the console
304
+ * project at all (AGL-1430's correspondence — do not break it).
305
+ * - **`degraded`** — Firestore could not be reached. Fails OPEN, matching the
306
+ * workspace gate and for the reason AGL-1135 recorded: the Vercel domain
307
+ * allowlist is the boundary, and a customer's console going dark because a
308
+ * lookup timed out is worse than the residual exposure. Never cached.
309
+ * - a claim that is `active` and entitled.
310
+ *
311
+ * Everything else refuses. In particular a `verified` claim is **not**
312
+ * servable: until AGL-1378 clears, activation includes a manual App Check
313
+ * allowlist entry, so "ownership proved" must never imply "serve it".
314
+ */
315
+ export declare function resolveConsoleDomain(host: string): Promise<ConsoleDomainVerdict>;
316
+ /**
317
+ * The org a console domain belongs to, or null.
318
+ *
319
+ * Read-only, and used today only to refuse a `customConsoleDomain` that another
320
+ * org already holds. Routing reads `resolveConsoleDomain` instead, which asks
321
+ * the entitlement question this one does not.
322
+ */
323
+ export declare function getConsoleDomainClaim(domain: string): Promise<{
324
+ orgId: string;
325
+ status: ConsoleDomainStatus;
326
+ } | null>;