@wtfalch/foundry 0.11.0 → 0.12.0

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.
@@ -604,6 +604,18 @@ export interface LettermintPort {
604
604
  */
605
605
  restrictDomainToProjects(domainId: string, projectIds: readonly string[]): Promise<void>;
606
606
  }
607
+ /**
608
+ * `OrgMailOrg` with `domain` required (#345): a relay route is keyed to a
609
+ * domain, and `OrgMailOrg.domain` is absent for a level-1 org (its domain is
610
+ * `${slug}.${apex}`, resolved only once `applyOrgMail` returns
611
+ * `OrgMailResult.domain`) -- so a caller of `MailPort`'s three relay methods
612
+ * below must already hold that resolved domain and pass it explicitly,
613
+ * rather than the port guessing or refusing on a level-1 org's bare
614
+ * `mailOrgFor` result.
615
+ */
616
+ export type OrgRelayMailOrg = OrgMailOrg & {
617
+ readonly domain: string;
618
+ };
607
619
  /**
608
620
  * The Stalwart calls this executor makes for one org's mail, shaped to match
609
621
  * `@wtfalch/email/postmaster`'s `applyOrgMail`/`parkOrgMail` method-for-method
@@ -639,25 +651,29 @@ export interface MailPort {
639
651
  * minted (`ensureOrgLettermintRelay`'s own mint rule) -- it goes straight
640
652
  * here and nowhere else: never returned, never recorded, never logged, the
641
653
  * same discipline `ensureAppLettermintMail`'s own doc comment states for
642
- * `LETTERMINT_API_TOKEN`.
654
+ * `LETTERMINT_API_TOKEN`. `org.domain` is required (#345): a level-1 org
655
+ * has none of its own on `OrgMailOrg`, so the caller passes the domain
656
+ * `applyOrgMail` already resolved for it.
643
657
  */
644
- applyOrgRelay(org: OrgMailOrg, secret: string): Promise<void>;
658
+ applyOrgRelay(org: OrgRelayMailOrg, secret: string): Promise<void>;
645
659
  /**
646
660
  * Drops this org's relay route (#149), implemented with
647
661
  * `@wtfalch/email/postmaster`'s own `removeOrgRelay` -- a missing route is
648
662
  * a no-op, so `parkLettermintMail` can call this unconditionally before it
649
- * deletes the Lettermint project the route pointed at.
663
+ * deletes the Lettermint project the route pointed at. `org.domain` is
664
+ * required (#345), the same reason {@link MailPort.applyOrgRelay} needs it.
650
665
  */
651
- removeOrgRelay(org: OrgMailOrg): Promise<void>;
666
+ removeOrgRelay(org: OrgRelayMailOrg): Promise<void>;
652
667
  /**
653
668
  * True once this org's relay route exists on Stalwart with a secret set
654
669
  * (#149). `ensureOrgLettermintRelay`'s own mint rule reads this alongside
655
670
  * Lettermint's own project listing: a project without a live route (the
656
671
  * route recorded a token this executor never minted) is exactly as
657
672
  * unhealthy as a route with no project behind it, so a fresh mint fixes
658
- * either.
673
+ * either. `org.domain` is required (#345), the same reason
674
+ * {@link MailPort.applyOrgRelay} needs it.
659
675
  */
660
- hasOrgRelay(org: OrgMailOrg): Promise<boolean>;
676
+ hasOrgRelay(org: OrgRelayMailOrg): Promise<boolean>;
661
677
  }
662
678
  /**
663
679
  * The shared calls SFU's own per-org LiveKit API credentials (#122, #127,
@@ -2343,9 +2343,13 @@ export class FoundryStepExecutor {
2343
2343
  */
2344
2344
  async ensureOrgLettermintRelay(org, mailOrg, mailDomain, context) {
2345
2345
  const relayName = `${org.slug}-relay`;
2346
+ // #345: `mailOrg.domain` is absent for a level-1 org -- `mailDomain` is
2347
+ // `applyOrgMail`'s own resolved result, the one domain `MailPort`'s
2348
+ // relay methods ever need.
2349
+ const relayOrg = { ...mailOrg, domain: mailDomain };
2346
2350
  const [projects, hasRelay] = await Promise.all([
2347
2351
  this.ports.lettermint.listProjects(),
2348
- this.ports.mail.hasOrgRelay(mailOrg),
2352
+ this.ports.mail.hasOrgRelay(relayOrg),
2349
2353
  ]);
2350
2354
  // The recorded project, not "the only one": a leftover duplicate whose
2351
2355
  // delete keeps failing must not force a fresh mint on every apply.
@@ -2368,7 +2372,7 @@ export class FoundryStepExecutor {
2368
2372
  // The restriction covers old and new projects, so the old one keeps
2369
2373
  // sending until the route switches.
2370
2374
  await this.ensureLettermintDomainRestriction(org, mailDomain, allProjects);
2371
- await this.ports.mail.applyOrgRelay(mailOrg, created.token);
2375
+ await this.ports.mail.applyOrgRelay(relayOrg, created.token);
2372
2376
  }
2373
2377
  catch (err) {
2374
2378
  await this.discardLettermintProject(created.project.id);
@@ -4061,7 +4065,9 @@ export class FoundryStepExecutor {
4061
4065
  const mailDomain = context.recordedIds()[MAIL_DOMAIN_SCOPE_KEY];
4062
4066
  if (!mailDomain)
4063
4067
  return;
4064
- await this.ports.mail.removeOrgRelay(mailOrg);
4068
+ // #345: `mailOrg.domain` is absent for a level-1 org -- the previously
4069
+ // recorded mail domain is the one `MailPort.removeOrgRelay` needs.
4070
+ await this.ports.mail.removeOrgRelay({ ...mailOrg, domain: mailDomain });
4065
4071
  const names = new Set([`${org.slug}-app`, `${org.slug}-relay`]);
4066
4072
  const projects = await this.ports.lettermint.listProjects();
4067
4073
  for (const project of projects) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/foundry",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Foundry's SDK: the declared org's types, the plan and apply contracts, and the state store's interface.",
5
5
  "repository": {
6
6
  "type": "git",