@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,184 @@
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
+ * One DNS lookup, pinned to public resolvers, that can say "I do not know".
18
+ *
19
+ * The same shape appeared independently in `/api/domains/verify` (AGL-734) and
20
+ * in `sso-provisioning.ts` (AGL-1210), and a third copy was about to be
21
+ * written for sending domains. It is here once instead.
22
+ *
23
+ * ## Why the resolvers are pinned
24
+ *
25
+ * The runtime's default resolver is not a neutral observer. A stale zone once
26
+ * made the hosting platform's own resolver return NXDOMAIN for records every
27
+ * public resolver could see, which reads as "the customer deleted their
28
+ * record" and is indistinguishable from the real thing. Asking a public
29
+ * resolver first, and falling back to the runtime's only when the pinned ones
30
+ * are unreachable, keeps a genuine "no such record" answer conclusive.
31
+ *
32
+ * ## Why there are three outcomes and not two
33
+ *
34
+ * A boolean cannot tell "the record is gone" from "nobody answered", and the
35
+ * difference decides whether a customer's working configuration gets marked
36
+ * broken during someone else's outage. `NXDOMAIN`/`ENOTFOUND`/`ENODATA` are
37
+ * ANSWERS — that name has no such record — and stay conclusive. Anything else,
38
+ * from both the pinned resolvers and the fallback, is `unreachable`, and a
39
+ * caller must treat it as evidence of nothing in either direction.
40
+ */ import { promises as dns, Resolver as CallbackResolver } from "dns";
41
+ /** Resolvers asked before the runtime's own. */ export const PUBLIC_DNS_RESOLVERS = [
42
+ '1.1.1.1',
43
+ '8.8.8.8'
44
+ ];
45
+ /** Whether a resolver error code is an answer rather than a failure to get one. */ export function isConclusiveDnsCode(code) {
46
+ return code === 'ENOTFOUND' || code === 'ENODATA' || code === 'NXDOMAIN';
47
+ }
48
+ /**
49
+ * TXT records at `host`, each joined from its chunks and trimmed.
50
+ *
51
+ * A TXT answer arrives as an array of string CHUNKS per record, because DNS
52
+ * splits strings longer than 255 bytes. Comparing without joining means a long
53
+ * value — every DKIM public key, for instance — can never match.
54
+ */ export async function lookupTxt(host) {
55
+ const flatten = (records)=>records.map((chunks)=>chunks.join('').trim());
56
+ try {
57
+ const resolver = new CallbackResolver();
58
+ resolver.setServers(PUBLIC_DNS_RESOLVERS);
59
+ const records = await new Promise((resolve, reject)=>{
60
+ resolver.resolveTxt(host, (error, addresses)=>error ? reject(error) : resolve(addresses));
61
+ });
62
+ return {
63
+ answered: true,
64
+ records: flatten(records)
65
+ };
66
+ } catch (error) {
67
+ const code = error == null ? void 0 : error.code;
68
+ if (isConclusiveDnsCode(code)) return {
69
+ answered: true,
70
+ records: []
71
+ };
72
+ try {
73
+ return {
74
+ answered: true,
75
+ records: flatten(await dns.resolveTxt(host))
76
+ };
77
+ } catch (fallbackError) {
78
+ const fallbackCode = fallbackError == null ? void 0 : fallbackError.code;
79
+ if (isConclusiveDnsCode(fallbackCode)) return {
80
+ answered: true,
81
+ records: []
82
+ };
83
+ return {
84
+ answered: false,
85
+ records: []
86
+ };
87
+ }
88
+ }
89
+ }
90
+ /**
91
+ * CAA records at `host`, as `<flags> <tag> "<value>"` strings.
92
+ *
93
+ * NOT walked up the tree. The caller asks about one exact name, because the
94
+ * question this exists for is "does THIS name publish a policy of its own",
95
+ * and a walk would answer a different one — a parent's policy is inherited by
96
+ * resolution, not by publication, and reporting the parent's records as the
97
+ * child's would say a name restricts issuance when it publishes nothing.
98
+ */ export async function lookupCaa(host) {
99
+ const normalize = (records)=>records.map((entry)=>{
100
+ var _ref, _ref1, _row_issue;
101
+ const row = entry;
102
+ const tag = (row == null ? void 0 : row.issue) !== undefined ? 'issue' : (row == null ? void 0 : row.issuewild) !== undefined ? 'issuewild' : (row == null ? void 0 : row.iodef) !== undefined ? 'iodef' : '';
103
+ if (!tag) return '';
104
+ const value = String((_ref = (_ref1 = (_row_issue = row.issue) != null ? _row_issue : row.issuewild) != null ? _ref1 : row.iodef) != null ? _ref : '').trim();
105
+ return `${Number(row == null ? void 0 : row.critical) || 0} ${tag} "${value}"`;
106
+ }).filter(Boolean);
107
+ try {
108
+ const resolver = new CallbackResolver();
109
+ resolver.setServers(PUBLIC_DNS_RESOLVERS);
110
+ const records = await new Promise((resolve, reject)=>{
111
+ resolver.resolveCaa(host, (error, addresses)=>error ? reject(error) : resolve(addresses));
112
+ });
113
+ return {
114
+ answered: true,
115
+ records: normalize(records)
116
+ };
117
+ } catch (error) {
118
+ const code = error == null ? void 0 : error.code;
119
+ if (isConclusiveDnsCode(code)) return {
120
+ answered: true,
121
+ records: []
122
+ };
123
+ try {
124
+ return {
125
+ answered: true,
126
+ records: normalize(await dns.resolveCaa(host))
127
+ };
128
+ } catch (fallbackError) {
129
+ const fallbackCode = fallbackError == null ? void 0 : fallbackError.code;
130
+ if (isConclusiveDnsCode(fallbackCode)) return {
131
+ answered: true,
132
+ records: []
133
+ };
134
+ return {
135
+ answered: false,
136
+ records: []
137
+ };
138
+ }
139
+ }
140
+ }
141
+ /** MX records at `host`, exchanges lowercased and stripped of a trailing dot. */ export async function lookupMx(host) {
142
+ const normalize = (records)=>records.map((entry)=>{
143
+ var _ref;
144
+ return {
145
+ exchange: String((_ref = entry == null ? void 0 : entry.exchange) != null ? _ref : '').trim().toLowerCase().replace(/\.$/, ''),
146
+ priority: Number(entry == null ? void 0 : entry.priority) || 0
147
+ };
148
+ });
149
+ try {
150
+ const resolver = new CallbackResolver();
151
+ resolver.setServers(PUBLIC_DNS_RESOLVERS);
152
+ const records = await new Promise((resolve, reject)=>{
153
+ resolver.resolveMx(host, (error, addresses)=>error ? reject(error) : resolve(addresses));
154
+ });
155
+ return {
156
+ answered: true,
157
+ records: normalize(records)
158
+ };
159
+ } catch (error) {
160
+ const code = error == null ? void 0 : error.code;
161
+ if (isConclusiveDnsCode(code)) return {
162
+ answered: true,
163
+ records: []
164
+ };
165
+ try {
166
+ return {
167
+ answered: true,
168
+ records: normalize(await dns.resolveMx(host))
169
+ };
170
+ } catch (fallbackError) {
171
+ const fallbackCode = fallbackError == null ? void 0 : fallbackError.code;
172
+ if (isConclusiveDnsCode(fallbackCode)) return {
173
+ answered: true,
174
+ records: []
175
+ };
176
+ return {
177
+ answered: false,
178
+ records: []
179
+ };
180
+ }
181
+ }
182
+ }
183
+
184
+ //# sourceMappingURL=dns-probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/dns-probe.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 * One DNS lookup, pinned to public resolvers, that can say \"I do not know\".\n *\n * The same shape appeared independently in `/api/domains/verify` (AGL-734) and\n * in `sso-provisioning.ts` (AGL-1210), and a third copy was about to be\n * written for sending domains. It is here once instead.\n *\n * ## Why the resolvers are pinned\n *\n * The runtime's default resolver is not a neutral observer. A stale zone once\n * made the hosting platform's own resolver return NXDOMAIN for records every\n * public resolver could see, which reads as \"the customer deleted their\n * record\" and is indistinguishable from the real thing. Asking a public\n * resolver first, and falling back to the runtime's only when the pinned ones\n * are unreachable, keeps a genuine \"no such record\" answer conclusive.\n *\n * ## Why there are three outcomes and not two\n *\n * A boolean cannot tell \"the record is gone\" from \"nobody answered\", and the\n * difference decides whether a customer's working configuration gets marked\n * broken during someone else's outage. `NXDOMAIN`/`ENOTFOUND`/`ENODATA` are\n * ANSWERS — that name has no such record — and stay conclusive. Anything else,\n * from both the pinned resolvers and the fallback, is `unreachable`, and a\n * caller must treat it as evidence of nothing in either direction.\n */\n\nimport { promises as dns, Resolver as CallbackResolver } from 'dns'\n\n/** Resolvers asked before the runtime's own. */\nexport const PUBLIC_DNS_RESOLVERS = ['1.1.1.1', '8.8.8.8']\n\n/** Whether a resolver error code is an answer rather than a failure to get one. */\nexport function isConclusiveDnsCode(code: string | undefined): boolean {\n return code === 'ENOTFOUND' || code === 'ENODATA' || code === 'NXDOMAIN'\n}\n\nexport interface DnsLookupResult<T> {\n /**\n * True when the lookup got an answer, including the answer \"there is\n * nothing here\". False only when nobody answered.\n */\n answered: boolean\n /** Empty on a conclusive miss and on an unreachable lookup alike. */\n records: T[]\n}\n\n/**\n * TXT records at `host`, each joined from its chunks and trimmed.\n *\n * A TXT answer arrives as an array of string CHUNKS per record, because DNS\n * splits strings longer than 255 bytes. Comparing without joining means a long\n * value — every DKIM public key, for instance — can never match.\n */\nexport async function lookupTxt(host: string): Promise<DnsLookupResult<string>> {\n const flatten = (records: string[][]) =>\n records.map((chunks) => chunks.join('').trim())\n\n try {\n const resolver = new CallbackResolver()\n resolver.setServers(PUBLIC_DNS_RESOLVERS)\n const records = await new Promise<string[][]>((resolve, reject) => {\n resolver.resolveTxt(host, (error, addresses) =>\n error ? reject(error) : resolve(addresses),\n )\n })\n return { answered: true, records: flatten(records) }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(code)) return { answered: true, records: [] }\n try {\n return { answered: true, records: flatten(await dns.resolveTxt(host)) }\n } catch (fallbackError) {\n const fallbackCode = (fallbackError as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(fallbackCode)) return { answered: true, records: [] }\n return { answered: false, records: [] }\n }\n }\n}\n\n/**\n * CAA records at `host`, as `<flags> <tag> \"<value>\"` strings.\n *\n * NOT walked up the tree. The caller asks about one exact name, because the\n * question this exists for is \"does THIS name publish a policy of its own\",\n * and a walk would answer a different one — a parent's policy is inherited by\n * resolution, not by publication, and reporting the parent's records as the\n * child's would say a name restricts issuance when it publishes nothing.\n */\nexport async function lookupCaa(host: string): Promise<DnsLookupResult<string>> {\n const normalize = (records: unknown[]) =>\n records\n .map((entry) => {\n const row = entry as { critical?: number; issue?: string; issuewild?: string; iodef?: string }\n const tag = row?.issue !== undefined\n ? 'issue'\n : row?.issuewild !== undefined\n ? 'issuewild'\n : row?.iodef !== undefined\n ? 'iodef'\n : ''\n if (!tag) return ''\n const value = String(\n row.issue ?? row.issuewild ?? row.iodef ?? '',\n ).trim()\n return `${Number(row?.critical) || 0} ${tag} \"${value}\"`\n })\n .filter(Boolean)\n\n try {\n const resolver = new CallbackResolver()\n resolver.setServers(PUBLIC_DNS_RESOLVERS)\n const records = await new Promise<unknown[]>((resolve, reject) => {\n resolver.resolveCaa(host, (error, addresses) =>\n error ? reject(error) : resolve(addresses as unknown[]),\n )\n })\n return { answered: true, records: normalize(records) }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(code)) return { answered: true, records: [] }\n try {\n return {\n answered: true,\n records: normalize((await dns.resolveCaa(host)) as unknown[]),\n }\n } catch (fallbackError) {\n const fallbackCode = (fallbackError as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(fallbackCode)) return { answered: true, records: [] }\n return { answered: false, records: [] }\n }\n }\n}\n\nexport interface MxRecord {\n exchange: string\n priority: number\n}\n\n/** MX records at `host`, exchanges lowercased and stripped of a trailing dot. */\nexport async function lookupMx(host: string): Promise<DnsLookupResult<MxRecord>> {\n const normalize = (records: { exchange: string; priority: number }[]) =>\n records.map((entry) => ({\n exchange: String(entry?.exchange ?? '')\n .trim()\n .toLowerCase()\n .replace(/\\.$/, ''),\n priority: Number(entry?.priority) || 0,\n }))\n\n try {\n const resolver = new CallbackResolver()\n resolver.setServers(PUBLIC_DNS_RESOLVERS)\n const records = await new Promise<{ exchange: string; priority: number }[]>(\n (resolve, reject) => {\n resolver.resolveMx(host, (error, addresses) =>\n error ? reject(error) : resolve(addresses),\n )\n },\n )\n return { answered: true, records: normalize(records) }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(code)) return { answered: true, records: [] }\n try {\n return { answered: true, records: normalize(await dns.resolveMx(host)) }\n } catch (fallbackError) {\n const fallbackCode = (fallbackError as NodeJS.ErrnoException)?.code\n if (isConclusiveDnsCode(fallbackCode)) return { answered: true, records: [] }\n return { answered: false, records: [] }\n }\n }\n}\n"],"names":["promises","dns","Resolver","CallbackResolver","PUBLIC_DNS_RESOLVERS","isConclusiveDnsCode","code","lookupTxt","host","flatten","records","map","chunks","join","trim","resolver","setServers","Promise","resolve","reject","resolveTxt","error","addresses","answered","fallbackError","fallbackCode","lookupCaa","normalize","entry","row","tag","issue","undefined","issuewild","iodef","value","String","Number","critical","filter","Boolean","resolveCaa","lookupMx","exchange","toLowerCase","replace","priority","resolveMx"],"mappings":"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"}
@@ -0,0 +1,29 @@
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
+ /** Firestore's document id ceiling, which the service counts in BYTES. */
18
+ export declare const MAX_DOCUMENT_ID_BYTES = 1500;
19
+ /**
20
+ * Whether `value` is usable as ONE opaque Firestore document id.
21
+ *
22
+ * Every clause is a path escape rather than a style preference: `/` is both
23
+ * the nesting hazard and the synchronous `.doc()` throw; `.` and `..` are
24
+ * traversal that Firestore rejects outright; the reserved form throws instead
25
+ * of reporting absence; and the length is Firestore's own limit, measured in
26
+ * UTF-8 bytes because that is what the limit counts — 376 emoji are 1504
27
+ * bytes and would sail through a `.length` check.
28
+ */
29
+ export declare function isDocumentId(value: unknown): value is string;
@@ -0,0 +1,100 @@
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
+ * `isDocumentId(value)` — may this value be handed to `.doc()` as ONE opaque
18
+ * document id (AGL-1771)?
19
+ *
20
+ * WHY THE QUESTION EXISTS. `CollectionReference.doc()` appends a
21
+ * SLASH-SEPARATED path and refuses it only when the resulting component count
22
+ * comes out odd (`@google-cloud/firestore`, `collection-reference.js`,
23
+ * measured in `842e72576`). It never treats its argument as one opaque id. So
24
+ * an unvalidated value taken from a request, a webhook tag, a cookie or a
25
+ * stored field gives three distinct failures, none of which is "not found":
26
+ *
27
+ * * an ODD component count (`a/b/c`) is a perfectly legal path, so the read
28
+ * or write lands beneath a document that does not exist — invisible to
29
+ * every console list, because they resolve the parent first;
30
+ * * an EVEN one (`half/path`) throws SYNCHRONOUSLY at the line building the
31
+ * ref, which is a different failure from a rejected promise and escapes
32
+ * any `.catch()` on one. Whether that becomes a clean 500 or rejects out
33
+ * of the handler depends entirely on whether the ref is built inside or
34
+ * outside the handler's `try`;
35
+ * * a reserved `__…__` id answers `INVALID_ARGUMENT` rather than an absent
36
+ * snapshot — the trap `542b1023f` hit with `products/__missing__`.
37
+ *
38
+ * WHY IT LIVES HERE. This is the third and fourth call site. AGL-1769 wrote
39
+ * the rule as `isCartId` in `libs/plugins/commerce/src/lib/server/cart-cookie.ts`
40
+ * and AGL-1768 copied it as a local `isDocumentId` in
41
+ * `libs/plugins/marketing/src/lib/server/email-events.ts`; AGL-1771's sweep
42
+ * then found two more handlers that need it. Duplication was the cheaper wait
43
+ * at two copies and stops being cheaper at four.
44
+ *
45
+ * A CORRECTION, since the second copy was made for a stated reason that turns
46
+ * out to be false: `@nx/enforce-module-boundaries` does NOT refuse an edge
47
+ * between two feature plugins. Every plugin carries only `aglyn:addons`, and
48
+ * that tag's rule lists `aglyn:addons` among its permitted targets — indeed
49
+ * `campaign-send.ts` already imports `@aglyn/plugins-commerce/model` today. The
50
+ * real objection to marketing importing commerce's cart-cookie module is not
51
+ * lint but sense: the predicate is not about carts, and reaching it through
52
+ * `@aglyn/plugins-commerce/server` would pull the whole commerce server graph
53
+ * — Stripe, the billing webhook — into the marketing plugin for six lines.
54
+ *
55
+ * `tenant-data-admin` is the right home instead because it is where Firestore
56
+ * paths are BUILT, and because {@link updateExisting} — the sibling primitive
57
+ * answering the same class of question, "must this document already exist?" —
58
+ * already lives beside it. Both plugins already depend on this library, so no
59
+ * new edge is created, and this module imports nothing, so none is created
60
+ * downstream either.
61
+ *
62
+ * IMPORT IT FROM THIS ENTRY POINT — `@aglyn/tenant-data-admin/server/document-id`
63
+ * — and not from the library barrel, which is exported there only for
64
+ * discoverability beside its siblings. Two reasons, both load-bearing:
65
+ *
66
+ * * this module imports NOTHING, and reaching it through `tenancy.ts` would
67
+ * pull ~35 server modules (media CDN, erasure, Next render-cache) into
68
+ * callers that today have no such graph. `cart-cookie.ts` imports only
69
+ * `crypto`; it should stay that way;
70
+ * * nearly every spec touching those callers already does
71
+ * `jest.mock('@aglyn/tenant-data-admin', …)` precisely because that graph
72
+ * will not load under jest. A barrel import would resolve to whatever the
73
+ * mock object happens to contain — `undefined` at best, and at worst a
74
+ * permissive stub that turns every path-shaped test value into a false
75
+ * green. A leaf entry point is not intercepted, so the predicate under test
76
+ * is always the real one.
77
+ *
78
+ * WHAT THIS IS NOT. Not an authorization check and not a claim that the
79
+ * document exists. It bounds a value to one path COMPONENT; whether that
80
+ * component names anything, and whether this caller may touch it, are separate
81
+ * questions that only the read, the write, or a gate can answer.
82
+ */ /**
83
+ * Firestore reserves ids matching `__…__` and rejects them with
84
+ * `INVALID_ARGUMENT` rather than returning an absent snapshot.
85
+ */ const RESERVED_DOCUMENT_ID = /^__.*__$/;
86
+ /** Firestore's document id ceiling, which the service counts in BYTES. */ export const MAX_DOCUMENT_ID_BYTES = 1500;
87
+ /**
88
+ * Whether `value` is usable as ONE opaque Firestore document id.
89
+ *
90
+ * Every clause is a path escape rather than a style preference: `/` is both
91
+ * the nesting hazard and the synchronous `.doc()` throw; `.` and `..` are
92
+ * traversal that Firestore rejects outright; the reserved form throws instead
93
+ * of reporting absence; and the length is Firestore's own limit, measured in
94
+ * UTF-8 bytes because that is what the limit counts — 376 emoji are 1504
95
+ * bytes and would sail through a `.length` check.
96
+ */ export function isDocumentId(value) {
97
+ return typeof value === 'string' && value.length > 0 && !value.includes('/') && value !== '.' && value !== '..' && !RESERVED_DOCUMENT_ID.test(value) && Buffer.byteLength(value, 'utf8') <= MAX_DOCUMENT_ID_BYTES;
98
+ }
99
+
100
+ //# sourceMappingURL=document-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/document-id.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 * `isDocumentId(value)` — may this value be handed to `.doc()` as ONE opaque\n * document id (AGL-1771)?\n *\n * WHY THE QUESTION EXISTS. `CollectionReference.doc()` appends a\n * SLASH-SEPARATED path and refuses it only when the resulting component count\n * comes out odd (`@google-cloud/firestore`, `collection-reference.js`,\n * measured in `842e72576`). It never treats its argument as one opaque id. So\n * an unvalidated value taken from a request, a webhook tag, a cookie or a\n * stored field gives three distinct failures, none of which is \"not found\":\n *\n * * an ODD component count (`a/b/c`) is a perfectly legal path, so the read\n * or write lands beneath a document that does not exist — invisible to\n * every console list, because they resolve the parent first;\n * * an EVEN one (`half/path`) throws SYNCHRONOUSLY at the line building the\n * ref, which is a different failure from a rejected promise and escapes\n * any `.catch()` on one. Whether that becomes a clean 500 or rejects out\n * of the handler depends entirely on whether the ref is built inside or\n * outside the handler's `try`;\n * * a reserved `__…__` id answers `INVALID_ARGUMENT` rather than an absent\n * snapshot — the trap `542b1023f` hit with `products/__missing__`.\n *\n * WHY IT LIVES HERE. This is the third and fourth call site. AGL-1769 wrote\n * the rule as `isCartId` in `libs/plugins/commerce/src/lib/server/cart-cookie.ts`\n * and AGL-1768 copied it as a local `isDocumentId` in\n * `libs/plugins/marketing/src/lib/server/email-events.ts`; AGL-1771's sweep\n * then found two more handlers that need it. Duplication was the cheaper wait\n * at two copies and stops being cheaper at four.\n *\n * A CORRECTION, since the second copy was made for a stated reason that turns\n * out to be false: `@nx/enforce-module-boundaries` does NOT refuse an edge\n * between two feature plugins. Every plugin carries only `aglyn:addons`, and\n * that tag's rule lists `aglyn:addons` among its permitted targets — indeed\n * `campaign-send.ts` already imports `@aglyn/plugins-commerce/model` today. The\n * real objection to marketing importing commerce's cart-cookie module is not\n * lint but sense: the predicate is not about carts, and reaching it through\n * `@aglyn/plugins-commerce/server` would pull the whole commerce server graph\n * — Stripe, the billing webhook — into the marketing plugin for six lines.\n *\n * `tenant-data-admin` is the right home instead because it is where Firestore\n * paths are BUILT, and because {@link updateExisting} — the sibling primitive\n * answering the same class of question, \"must this document already exist?\" —\n * already lives beside it. Both plugins already depend on this library, so no\n * new edge is created, and this module imports nothing, so none is created\n * downstream either.\n *\n * IMPORT IT FROM THIS ENTRY POINT — `@aglyn/tenant-data-admin/server/document-id`\n * — and not from the library barrel, which is exported there only for\n * discoverability beside its siblings. Two reasons, both load-bearing:\n *\n * * this module imports NOTHING, and reaching it through `tenancy.ts` would\n * pull ~35 server modules (media CDN, erasure, Next render-cache) into\n * callers that today have no such graph. `cart-cookie.ts` imports only\n * `crypto`; it should stay that way;\n * * nearly every spec touching those callers already does\n * `jest.mock('@aglyn/tenant-data-admin', …)` precisely because that graph\n * will not load under jest. A barrel import would resolve to whatever the\n * mock object happens to contain — `undefined` at best, and at worst a\n * permissive stub that turns every path-shaped test value into a false\n * green. A leaf entry point is not intercepted, so the predicate under test\n * is always the real one.\n *\n * WHAT THIS IS NOT. Not an authorization check and not a claim that the\n * document exists. It bounds a value to one path COMPONENT; whether that\n * component names anything, and whether this caller may touch it, are separate\n * questions that only the read, the write, or a gate can answer.\n */\n\n/**\n * Firestore reserves ids matching `__…__` and rejects them with\n * `INVALID_ARGUMENT` rather than returning an absent snapshot.\n */\nconst RESERVED_DOCUMENT_ID = /^__.*__$/\n\n/** Firestore's document id ceiling, which the service counts in BYTES. */\nexport const MAX_DOCUMENT_ID_BYTES = 1500\n\n/**\n * Whether `value` is usable as ONE opaque Firestore document id.\n *\n * Every clause is a path escape rather than a style preference: `/` is both\n * the nesting hazard and the synchronous `.doc()` throw; `.` and `..` are\n * traversal that Firestore rejects outright; the reserved form throws instead\n * of reporting absence; and the length is Firestore's own limit, measured in\n * UTF-8 bytes because that is what the limit counts — 376 emoji are 1504\n * bytes and would sail through a `.length` check.\n */\nexport function isDocumentId(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n !value.includes('/') &&\n value !== '.' &&\n value !== '..' &&\n !RESERVED_DOCUMENT_ID.test(value) &&\n Buffer.byteLength(value, 'utf8') <= MAX_DOCUMENT_ID_BYTES\n )\n}\n"],"names":["RESERVED_DOCUMENT_ID","MAX_DOCUMENT_ID_BYTES","isDocumentId","value","length","includes","test","Buffer","byteLength"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkEC,GAED;;;CAGC,GACD,MAAMA,uBAAuB;AAE7B,wEAAwE,GACxE,OAAO,MAAMC,wBAAwB,KAAI;AAEzC;;;;;;;;;CASC,GACD,OAAO,SAASC,aAAaC,KAAc;IACzC,OACE,OAAOA,UAAU,YACjBA,MAAMC,MAAM,GAAG,KACf,CAACD,MAAME,QAAQ,CAAC,QAChBF,UAAU,OACVA,UAAU,QACV,CAACH,qBAAqBM,IAAI,CAACH,UAC3BI,OAAOC,UAAU,CAACL,OAAO,WAAWF;AAExC"}
@@ -0,0 +1,33 @@
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
+ * The Vercel driver — how Aglyn's own hosting registers a name.
19
+ *
20
+ * One implementation of the call, one deadline, one never-throws contract. It
21
+ * was five copies before this file existed: `workspace-domains.ts`, three
22
+ * console routes and `subdomain-redirect.ts` each held their own `fetch` to
23
+ * `api.vercel.com`, which is how two copies of a constant drift apart — the
24
+ * bug AGL-1135 was, one layer down.
25
+ *
26
+ * ## The two projects
27
+ *
28
+ * The console and the tenant runtime are separate Vercel projects, so the
29
+ * scope picks the id. One token and one team serve both: a second variable for
30
+ * the same token is the drift this file exists to prevent.
31
+ */
32
+ import { type DomainProvider } from './domain-provider';
33
+ export declare const VERCEL_DOMAIN_PROVIDER: DomainProvider;