@aglyn/tenant-data-admin 1.0.0-beta.200 → 1.0.0-beta.202

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 (67) hide show
  1. package/package.json +8 -7
  2. package/src/lib/server/card-payment-velocity.d.ts +85 -0
  3. package/src/lib/server/card-payment-velocity.js +202 -0
  4. package/src/lib/server/card-payment-velocity.js.map +1 -0
  5. package/src/lib/server/configured-url-fetch.d.ts +42 -0
  6. package/src/lib/server/configured-url-fetch.js +118 -0
  7. package/src/lib/server/configured-url-fetch.js.map +1 -0
  8. package/src/lib/server/dns-probe.d.ts +7 -0
  9. package/src/lib/server/dns-probe.js +52 -0
  10. package/src/lib/server/dns-probe.js.map +1 -1
  11. package/src/lib/server/email-deliverability.d.ts +150 -0
  12. package/src/lib/server/email-deliverability.js +538 -0
  13. package/src/lib/server/email-deliverability.js.map +1 -0
  14. package/src/lib/server/email-sender-reputation.d.ts +2 -11
  15. package/src/lib/server/email-sender-reputation.js +8 -25
  16. package/src/lib/server/email-sender-reputation.js.map +1 -1
  17. package/src/lib/server/email-suppression.d.ts +10 -1
  18. package/src/lib/server/email-suppression.js +4 -3
  19. package/src/lib/server/email-suppression.js.map +1 -1
  20. package/src/lib/server/erase-person.js +31 -3
  21. package/src/lib/server/erase-person.js.map +1 -1
  22. package/src/lib/server/host-visitor-records.d.ts +16 -2
  23. package/src/lib/server/host-visitor-records.js +31 -6
  24. package/src/lib/server/host-visitor-records.js.map +1 -1
  25. package/src/lib/server/hosted-page-review.d.ts +112 -0
  26. package/src/lib/server/hosted-page-review.js +378 -0
  27. package/src/lib/server/hosted-page-review.js.map +1 -0
  28. package/src/lib/server/member-email-aliases.js +18 -7
  29. package/src/lib/server/member-email-aliases.js.map +1 -1
  30. package/src/lib/server/notifications.d.ts +8 -0
  31. package/src/lib/server/notifications.js +92 -17
  32. package/src/lib/server/notifications.js.map +1 -1
  33. package/src/lib/server/org-age.d.ts +27 -0
  34. package/src/lib/server/org-age.js +44 -0
  35. package/src/lib/server/org-age.js.map +1 -0
  36. package/src/lib/server/org-member-notice.js +20 -5
  37. package/src/lib/server/org-member-notice.js.map +1 -1
  38. package/src/lib/server/organizations.d.ts +10 -1
  39. package/src/lib/server/organizations.js +12 -4
  40. package/src/lib/server/organizations.js.map +1 -1
  41. package/src/lib/server/outbound-send-review.d.ts +224 -0
  42. package/src/lib/server/outbound-send-review.js +479 -0
  43. package/src/lib/server/outbound-send-review.js.map +1 -0
  44. package/src/lib/server/payment-fraud-signal.d.ts +156 -0
  45. package/src/lib/server/payment-fraud-signal.js +368 -0
  46. package/src/lib/server/payment-fraud-signal.js.map +1 -0
  47. package/src/lib/server/payment-risk-record.d.ts +59 -0
  48. package/src/lib/server/payment-risk-record.js +76 -0
  49. package/src/lib/server/payment-risk-record.js.map +1 -0
  50. package/src/lib/server/render-system-email.d.ts +176 -0
  51. package/src/lib/server/render-system-email.js +315 -0
  52. package/src/lib/server/render-system-email.js.map +1 -0
  53. package/src/lib/server/sending-domains.d.ts +6 -0
  54. package/src/lib/server/sending-domains.js +98 -6
  55. package/src/lib/server/sending-domains.js.map +1 -1
  56. package/src/lib/server/staff-alert-email.d.ts +2 -1
  57. package/src/lib/server/staff-alert-email.js +16 -5
  58. package/src/lib/server/staff-alert-email.js.map +1 -1
  59. package/src/lib/server/stripe-card-authentication.d.ts +35 -0
  60. package/src/lib/server/stripe-card-authentication.js +63 -0
  61. package/src/lib/server/stripe-card-authentication.js.map +1 -0
  62. package/src/lib/server/tenant-write-lockdown.d.ts +32 -2
  63. package/src/lib/server/tenant-write-lockdown.js +33 -3
  64. package/src/lib/server/tenant-write-lockdown.js.map +1 -1
  65. package/src/tenancy.d.ts +5 -0
  66. package/src/tenancy.js +10 -0
  67. package/src/tenancy.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/org-member-notice.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 { isEmailConfigured, sendEmail } from '@aglyn/shared-util-email'\nimport { findUserByUidAcrossPools } from './auth-pools'\nimport { filterSuppressedEmails } from './email-suppression'\nimport { listOrgMembers } from './organizations'\n\n/**\n * A NOTICE TO NAMED MEMBERS OF AN ORGANIZATION, BY EMAIL (AGL-3244).\n *\n * The console notification (`notifications.ts`) is the record, and its email\n * channel is a preference that defaults off. Some things cannot wait on a\n * preference: a sequence mailbox that paused itself holds every enrollment\n * on it until its owner acts, and the owner is not watching the page. This\n * sends the email regardless, to the members named and — when asked — to\n * the organization's owners and admins beside them, one send per address\n * so nobody is shown anyone else's.\n *\n * Addresses come from the roster (`orgs/{orgId}/members/{uid}.email`), and\n * for a member whose row carries none, from the directory. Suppressed\n * addresses are skipped, the send is metered to the organization, and\n * nothing here throws: the notice is a courtesy beside a state the caller\n * already wrote.\n */\n\nexport interface OrgMemberNoticeInput {\n orgId: string\n /** The members to write to, by uid. */\n uids: readonly string[]\n /** Also the organization's owners and admins. */\n includeAdmins?: boolean\n subject: string\n text: string\n /** Resend tag / log label. */\n context: string\n}\n\nexport interface OrgMemberNoticeResult {\n /** Addresses the notice went to. */\n sent: number\n /** Why nothing could be sent at all, when nothing could. */\n reason?: 'unconfigured' | 'no-recipients' | 'failed'\n}\n\n/** At most this many directory lookups, and this many sends, per notice. */\nconst MAX_LOOKUPS = 10\nconst MAX_SENDS = 25\n\n/** Sends one notice to each member — see the module note. */\nexport async function sendOrgMemberNotice(input: OrgMemberNoticeInput): Promise<OrgMemberNoticeResult> {\n if (!isEmailConfigured()) return { sent: 0, reason: 'unconfigured' }\n try {\n const members = await listOrgMembers(input.orgId)\n const rosterEmail = new Map<string, string>()\n for (const member of members) {\n const address = String(member.email ?? '')\n .trim()\n .toLowerCase()\n if (address.includes('@')) rosterEmail.set(member.$id, address)\n }\n const uids = new Set(input.uids.filter(Boolean))\n if (input.includeAdmins) {\n for (const member of members) {\n if (member.role === 'owner' || member.role === 'admin') uids.add(member.$id)\n }\n }\n const addresses = new Set<string>()\n let lookups = 0\n for (const uid of uids) {\n let address = rosterEmail.get(uid) ?? ''\n if (!address && lookups < MAX_LOOKUPS) {\n lookups += 1\n const pooled = await findUserByUidAcrossPools(uid).catch(() => null)\n address = String(pooled?.record?.email ?? '')\n .trim()\n .toLowerCase()\n }\n if (address.includes('@')) addresses.add(address)\n }\n const recipients = await filterSuppressedEmails([...addresses])\n if (!recipients.length) return { sent: 0, reason: 'no-recipients' }\n let sent = 0\n for (const to of recipients.slice(0, MAX_SENDS)) {\n const result = await sendEmail({ to, subject: input.subject, text: input.text, context: input.context })\n if (!result.sent) continue\n sent += 1\n const { meterOrgEmail } = await import('./email-metering')\n await meterOrgEmail(input.orgId).catch(() => undefined)\n }\n return sent ? { sent } : { sent: 0, reason: 'failed' }\n } catch (error) {\n console.error('[org-member-notice] send failed', error)\n return { sent: 0, reason: 'failed' }\n }\n}\n"],"names":["isEmailConfigured","sendEmail","findUserByUidAcrossPools","filterSuppressedEmails","listOrgMembers","MAX_LOOKUPS","MAX_SENDS","sendOrgMemberNotice","input","sent","reason","members","orgId","rosterEmail","Map","member","address","String","email","trim","toLowerCase","includes","set","$id","uids","Set","filter","Boolean","includeAdmins","role","add","addresses","lookups","uid","get","pooled","catch","record","recipients","length","to","slice","result","subject","text","context","meterOrgEmail","undefined","error","console"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,iBAAiB,EAAEC,SAAS,QAAQ,2BAA0B;AACvE,SAASC,wBAAwB,QAAQ,kBAAc;AACvD,SAASC,sBAAsB,QAAQ,yBAAqB;AAC5D,SAASC,cAAc,QAAQ,qBAAiB;AAuChD,0EAA0E,GAC1E,MAAMC,cAAc;AACpB,MAAMC,YAAY;AAElB,2DAA2D,GAC3D,OAAO,eAAeC,oBAAoBC,KAA2B;IACnE,IAAI,CAACR,qBAAqB,OAAO;QAAES,MAAM;QAAGC,QAAQ;IAAe;IACnE,IAAI;QACF,MAAMC,UAAU,MAAMP,eAAeI,MAAMI,KAAK;QAChD,MAAMC,cAAc,IAAIC;QACxB,KAAK,MAAMC,UAAUJ,QAAS;gBACLI;YAAvB,MAAMC,UAAUC,QAAOF,gBAAAA,OAAOG,KAAK,YAAZH,gBAAgB,IACpCI,IAAI,GACJC,WAAW;YACd,IAAIJ,QAAQK,QAAQ,CAAC,MAAMR,YAAYS,GAAG,CAACP,OAAOQ,GAAG,EAAEP;QACzD;QACA,MAAMQ,OAAO,IAAIC,IAAIjB,MAAMgB,IAAI,CAACE,MAAM,CAACC;QACvC,IAAInB,MAAMoB,aAAa,EAAE;YACvB,KAAK,MAAMb,UAAUJ,QAAS;gBAC5B,IAAII,OAAOc,IAAI,KAAK,WAAWd,OAAOc,IAAI,KAAK,SAASL,KAAKM,GAAG,CAACf,OAAOQ,GAAG;YAC7E;QACF;QACA,MAAMQ,YAAY,IAAIN;QACtB,IAAIO,UAAU;QACd,KAAK,MAAMC,OAAOT,KAAM;gBACRX;YAAd,IAAIG,WAAUH,mBAAAA,YAAYqB,GAAG,CAACD,gBAAhBpB,mBAAwB;YACtC,IAAI,CAACG,WAAWgB,UAAU3B,aAAa;;oBAGpB8B;gBAFjBH,WAAW;gBACX,MAAMG,SAAS,MAAMjC,yBAAyB+B,KAAKG,KAAK,CAAC,IAAM;gBAC/DpB,UAAUC,eAAOkB,2BAAAA,iBAAAA,OAAQE,MAAM,qBAAdF,eAAgBjB,KAAK,mBAAI,IACvCC,IAAI,GACJC,WAAW;YAChB;YACA,IAAIJ,QAAQK,QAAQ,CAAC,MAAMU,UAAUD,GAAG,CAACd;QAC3C;QACA,MAAMsB,aAAa,MAAMnC,uBAAuB;eAAI4B;SAAU;QAC9D,IAAI,CAACO,WAAWC,MAAM,EAAE,OAAO;YAAE9B,MAAM;YAAGC,QAAQ;QAAgB;QAClE,IAAID,OAAO;QACX,KAAK,MAAM+B,MAAMF,WAAWG,KAAK,CAAC,GAAGnC,WAAY;YAC/C,MAAMoC,SAAS,MAAMzC,UAAU;gBAAEuC;gBAAIG,SAASnC,MAAMmC,OAAO;gBAAEC,MAAMpC,MAAMoC,IAAI;gBAAEC,SAASrC,MAAMqC,OAAO;YAAC;YACtG,IAAI,CAACH,OAAOjC,IAAI,EAAE;YAClBA,QAAQ;YACR,MAAM,EAAEqC,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC;YACvC,MAAMA,cAActC,MAAMI,KAAK,EAAEwB,KAAK,CAAC,IAAMW;QAC/C;QACA,OAAOtC,OAAO;YAAEA;QAAK,IAAI;YAAEA,MAAM;YAAGC,QAAQ;QAAS;IACvD,EAAE,OAAOsC,OAAO;QACdC,QAAQD,KAAK,CAAC,mCAAmCA;QACjD,OAAO;YAAEvC,MAAM;YAAGC,QAAQ;QAAS;IACrC;AACF"}
1
+ {"version":3,"sources":["../../../../../../../../libs/tenant/data/admin/src/lib/server/org-member-notice.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 { isEmailConfigured, sendEmail } from '@aglyn/shared-util-email'\nimport { findUserByUidAcrossPools } from './auth-pools'\nimport { filterSuppressedEmails } from './email-suppression'\nimport { listOrgMembers } from './organizations'\nimport { orgSystemEmailBrand, renderSystemEmailContent } from './render-system-email'\n\n/**\n * A NOTICE TO NAMED MEMBERS OF AN ORGANIZATION, BY EMAIL (AGL-3244).\n *\n * The console notification (`notifications.ts`) is the record, and its email\n * channel is a preference that defaults off. Some things cannot wait on a\n * preference: a sequence mailbox that paused itself holds every enrollment\n * on it until its owner acts, and the owner is not watching the page. This\n * sends the email regardless, to the members named and — when asked — to\n * the organization's owners and admins beside them, one send per address\n * so nobody is shown anyone else's.\n *\n * Addresses come from the roster (`orgs/{orgId}/members/{uid}.email`), and\n * for a member whose row carries none, from the directory. Suppressed\n * addresses are skipped, the send is metered to the organization, and\n * nothing here throws: the notice is a courtesy beside a state the caller\n * already wrote.\n */\n\nexport interface OrgMemberNoticeInput {\n orgId: string\n /** The members to write to, by uid. */\n uids: readonly string[]\n /** Also the organization's owners and admins. */\n includeAdmins?: boolean\n subject: string\n text: string\n /** Resend tag / log label. */\n context: string\n}\n\nexport interface OrgMemberNoticeResult {\n /** Addresses the notice went to. */\n sent: number\n /** Why nothing could be sent at all, when nothing could. */\n reason?: 'unconfigured' | 'no-recipients' | 'failed'\n}\n\n/** At most this many directory lookups, and this many sends, per notice. */\nconst MAX_LOOKUPS = 10\nconst MAX_SENDS = 25\n\n/** Sends one notice to each member — see the module note. */\nexport async function sendOrgMemberNotice(input: OrgMemberNoticeInput): Promise<OrgMemberNoticeResult> {\n if (!isEmailConfigured()) return { sent: 0, reason: 'unconfigured' }\n try {\n const members = await listOrgMembers(input.orgId)\n const rosterEmail = new Map<string, string>()\n for (const member of members) {\n const address = String(member.email ?? '')\n .trim()\n .toLowerCase()\n if (address.includes('@')) rosterEmail.set(member.$id, address)\n }\n const uids = new Set(input.uids.filter(Boolean))\n if (input.includeAdmins) {\n for (const member of members) {\n if (member.role === 'owner' || member.role === 'admin') uids.add(member.$id)\n }\n }\n const addresses = new Set<string>()\n let lookups = 0\n for (const uid of uids) {\n let address = rosterEmail.get(uid) ?? ''\n if (!address && lookups < MAX_LOOKUPS) {\n lookups += 1\n const pooled = await findUserByUidAcrossPools(uid).catch(() => null)\n address = String(pooled?.record?.email ?? '')\n .trim()\n .toLowerCase()\n }\n if (address.includes('@')) addresses.add(address)\n }\n const recipients = await filterSuppressedEmails([...addresses])\n if (!recipients.length) return { sent: 0, reason: 'no-recipients' }\n // One message for everyone, in the organization's brand, as the\n // `workspace-notice` system email (AGL-3367).\n const brand = await orgSystemEmailBrand(input.orgId)\n const content = await renderSystemEmailContent(\n 'workspace-notice',\n {\n 'notice.subject': input.subject,\n 'notice.body': input.text,\n 'org.name': brand.orgName ?? '',\n },\n brand,\n { subject: input.subject, text: input.text },\n )\n let sent = 0\n for (const to of recipients.slice(0, MAX_SENDS)) {\n const result = await sendEmail({\n to,\n ...content,\n ...(brand.fromName ? { fromName: brand.fromName } : {}),\n context: input.context,\n })\n if (!result.sent) continue\n sent += 1\n const { meterOrgEmail } = await import('./email-metering')\n await meterOrgEmail(input.orgId).catch(() => undefined)\n }\n return sent ? { sent } : { sent: 0, reason: 'failed' }\n } catch (error) {\n console.error('[org-member-notice] send failed', error)\n return { sent: 0, reason: 'failed' }\n }\n}\n"],"names":["isEmailConfigured","sendEmail","findUserByUidAcrossPools","filterSuppressedEmails","listOrgMembers","orgSystemEmailBrand","renderSystemEmailContent","MAX_LOOKUPS","MAX_SENDS","sendOrgMemberNotice","input","sent","reason","brand","members","orgId","rosterEmail","Map","member","address","String","email","trim","toLowerCase","includes","set","$id","uids","Set","filter","Boolean","includeAdmins","role","add","addresses","lookups","uid","get","pooled","catch","record","recipients","length","content","subject","text","orgName","to","slice","result","fromName","context","meterOrgEmail","undefined","error","console"],"mappings":"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"}
@@ -423,7 +423,16 @@ export declare function logOrgActivity(orgId: string,
423
423
  actor: {
424
424
  uid: string | null;
425
425
  email?: string | null;
426
- }, action: string, target: OrgActivityTarget): Promise<void>;
426
+ }, action: string, target: OrgActivityTarget,
427
+ /**
428
+ * `staffActorId`: the staff member behind an entry the workspace did not
429
+ * perform (a staff cancellation, AGL-3369). Kept apart from `actorId` so
430
+ * the filterable actor stays honest; `/api/orgs/activity` shows it to
431
+ * staff only.
432
+ */
433
+ options?: {
434
+ staffActorId?: string | null;
435
+ }): Promise<void>;
427
436
  /** What a host activity entry points at. Mirrors `HostActivityTarget`. */
428
437
  export interface HostActivityTarget {
429
438
  type: 'host' | 'screen' | 'layout' | 'theme' | 'media' | 'content' | 'variable' | 'function' | 'workflow' | 'member' | 'component' | 'template' | 'contact' | 'company' | 'deal' | 'lead';
@@ -898,11 +898,19 @@ const MEMBER_PROJECTION_WRITE = {
898
898
  * performed — and `actorId` is a filterable field, so the invented
899
899
  * attribution would then show up under that person when somebody asks what
900
900
  * they have done.
901
- */ actor, action, target) {
901
+ */ actor, action, target, /**
902
+ * `staffActorId`: the staff member behind an entry the workspace did not
903
+ * perform (a staff cancellation, AGL-3369). Kept apart from `actorId` so
904
+ * the filterable actor stays honest; `/api/orgs/activity` shows it to
905
+ * staff only.
906
+ */ options) {
902
907
  var _actor_uid, _actor_email;
903
- await firestore().collection('orgs').doc(orgId).collection('activity').add({
908
+ await firestore().collection('orgs').doc(orgId).collection('activity').add(_extends({
904
909
  actorId: (_actor_uid = actor.uid) != null ? _actor_uid : null,
905
- actorEmail: (_actor_email = actor.email) != null ? _actor_email : null,
910
+ actorEmail: (_actor_email = actor.email) != null ? _actor_email : null
911
+ }, (options == null ? void 0 : options.staffActorId) ? {
912
+ staffActorId: options.staffActorId
913
+ } : {}, {
906
914
  action,
907
915
  target: _extends({
908
916
  type: target.type
@@ -919,7 +927,7 @@ const MEMBER_PROJECTION_WRITE = {
919
927
  target
920
928
  }),
921
929
  createdAt: FieldValue.serverTimestamp()
922
- }).catch(()=>undefined);
930
+ })).catch(()=>undefined);
923
931
  }
924
932
  /**
925
933
  * Append to `hosts/{hostId}/activity` with the ADMIN SDK (AGL-118).