@stacksjs/ts-cloud 0.7.103 → 0.7.104

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 (60) hide show
  1. package/dist/aws/index.js +14 -2
  2. package/dist/bin/cli.js +369 -369
  3. package/dist/bin/dashboard-server.js +203 -203
  4. package/dist/{chunk-ef2dwfrg.js → chunk-5cz14833.js} +3 -3
  5. package/dist/{chunk-gttvakpv.js → chunk-6hymgy61.js} +85 -1
  6. package/dist/{chunk-s9c2x5jv.js → chunk-adgz2c49.js} +2 -2
  7. package/dist/{chunk-vkd2y0fs.js → chunk-gtz4jar2.js} +1 -1
  8. package/dist/deploy/index.js +3 -3
  9. package/dist/dns/index.d.ts +2 -0
  10. package/dist/dns/index.js +14 -2
  11. package/dist/dns/mail-records.d.ts +82 -0
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.js +16 -4
  14. package/dist/ui/access-denied.html +2 -2
  15. package/dist/ui/account/automation.html +4 -4
  16. package/dist/ui/account/security.html +2 -2
  17. package/dist/ui/applications/compose.html +4 -4
  18. package/dist/ui/data/backups.html +4 -4
  19. package/dist/ui/data/services.html +4 -4
  20. package/dist/ui/data/volumes.html +4 -4
  21. package/dist/ui/index.html +4 -4
  22. package/dist/ui/integrations.html +2 -2
  23. package/dist/ui/operations/alerts.html +4 -4
  24. package/dist/ui/operations/configuration.html +4 -4
  25. package/dist/ui/operations/jobs.html +4 -4
  26. package/dist/ui/operations/maintenance.html +4 -4
  27. package/dist/ui/operations/observability.html +4 -4
  28. package/dist/ui/operations/previews.html +4 -4
  29. package/dist/ui/operations/queue.html +4 -4
  30. package/dist/ui/operations/regions.html +4 -4
  31. package/dist/ui/operations/releases.html +4 -4
  32. package/dist/ui/operations/workloads.html +4 -4
  33. package/dist/ui/security.html +2 -2
  34. package/dist/ui/server/actions.html +4 -4
  35. package/dist/ui/server/activity.html +2 -2
  36. package/dist/ui/server/capacity.html +4 -4
  37. package/dist/ui/server/database.html +4 -4
  38. package/dist/ui/server/deployments.html +4 -4
  39. package/dist/ui/server/firewall.html +4 -4
  40. package/dist/ui/server/fleet.html +3 -3
  41. package/dist/ui/server/logs.html +4 -4
  42. package/dist/ui/server/metrics.html +4 -4
  43. package/dist/ui/server/services.html +2 -2
  44. package/dist/ui/server/sites.html +4 -4
  45. package/dist/ui/server/ssh-keys.html +4 -4
  46. package/dist/ui/server/team.html +4 -4
  47. package/dist/ui/server/terminal.html +2 -2
  48. package/dist/ui/serverless/alarms.html +4 -4
  49. package/dist/ui/serverless/assets.html +2 -2
  50. package/dist/ui/serverless/cost.html +2 -2
  51. package/dist/ui/serverless/data.html +4 -4
  52. package/dist/ui/serverless/deployments.html +2 -2
  53. package/dist/ui/serverless/firewall.html +2 -2
  54. package/dist/ui/serverless/functions.html +4 -4
  55. package/dist/ui/serverless/logs.html +4 -4
  56. package/dist/ui/serverless/queues.html +4 -4
  57. package/dist/ui/serverless/secrets.html +4 -4
  58. package/dist/ui/serverless/traces.html +4 -4
  59. package/dist/ui/serverless.html +4 -4
  60. package/package.json +3 -3
@@ -7,7 +7,7 @@ import {
7
7
  Route53Provider,
8
8
  UnifiedDnsValidator,
9
9
  createDnsProvider
10
- } from "./chunk-gttvakpv.js";
10
+ } from "./chunk-6hymgy61.js";
11
11
  import {
12
12
  CloudFormationClient
13
13
  } from "./chunk-4cjrg98a.js";
@@ -815,7 +815,7 @@ async function deployStaticSiteWithExternalDnsFull(config) {
815
815
  }
816
816
  }
817
817
  onProgress?.("upload", "Uploading files to S3...");
818
- const { uploadStaticFiles } = await import("./chunk-s9c2x5jv.js");
818
+ const { uploadStaticFiles } = await import("./chunk-adgz2c49.js");
819
819
  const uploadResult = await uploadStaticFiles({
820
820
  sourceDir,
821
821
  bucket: infraResult.bucket,
@@ -835,7 +835,7 @@ async function deployStaticSiteWithExternalDnsFull(config) {
835
835
  }
836
836
  if (infraResult.distributionId && uploadResult.uploaded > 0) {
837
837
  onProgress?.("invalidate", "Invalidating CloudFront cache...");
838
- const { invalidateCache } = await import("./chunk-s9c2x5jv.js");
838
+ const { invalidateCache } = await import("./chunk-adgz2c49.js");
839
839
  await invalidateCache(infraResult.distributionId);
840
840
  }
841
841
  onProgress?.("complete", "Deployment complete!");
@@ -306,6 +306,90 @@ class PorkbunProvider {
306
306
  }
307
307
  }
308
308
  }
309
+ // src/dns/mail-records.ts
310
+ function buildSpfValue(options) {
311
+ const mechanisms = ["v=spf1"];
312
+ if (options.ip)
313
+ mechanisms.push(`ip4:${options.ip}`);
314
+ for (const include of options.spfIncludes || []) {
315
+ mechanisms.push(include.startsWith("include:") ? include : `include:${include}`);
316
+ }
317
+ mechanisms.push("~all");
318
+ return mechanisms.join(" ");
319
+ }
320
+ function normalizeDkimKey(key) {
321
+ return String(key || "").replace(/-----(?:BEGIN|END)[^-]*-----/g, "").replace(/\s+/g, "");
322
+ }
323
+ function buildDkimValue(publicKey) {
324
+ return `v=DKIM1; k=rsa; p=${normalizeDkimKey(publicKey)}`;
325
+ }
326
+ function buildDmarcValue(options) {
327
+ const parts = [`v=DMARC1`, `p=${options.dmarcPolicy || "none"}`];
328
+ if (options.dmarcReportTo)
329
+ parts.push(`rua=mailto:${options.dmarcReportTo}`);
330
+ return `${parts.join("; ")};`;
331
+ }
332
+ function buildMailDnsRecords(options) {
333
+ if (!options.domain)
334
+ throw new Error("A domain is required to build mail DNS records.");
335
+ if (!options.mailHost)
336
+ throw new Error("A mail host is required to build mail DNS records.");
337
+ const ttl = options.ttl ?? 600;
338
+ const selector = options.dkimSelector || "default";
339
+ const records = [
340
+ {
341
+ name: "@",
342
+ type: "MX",
343
+ content: options.mailHost,
344
+ priority: options.mxPriority ?? 10,
345
+ ttl
346
+ },
347
+ {
348
+ name: "@",
349
+ type: "TXT",
350
+ content: buildSpfValue(options),
351
+ ttl
352
+ },
353
+ {
354
+ name: "_dmarc",
355
+ type: "TXT",
356
+ content: buildDmarcValue(options),
357
+ ttl
358
+ }
359
+ ];
360
+ if (normalizeDkimKey(options.dkimPublicKey || "")) {
361
+ records.push({
362
+ name: `${selector}._domainkey`,
363
+ type: "TXT",
364
+ content: buildDkimValue(options.dkimPublicKey),
365
+ ttl
366
+ });
367
+ }
368
+ return records;
369
+ }
370
+ async function syncMailDns(provider, options) {
371
+ const records = buildMailDnsRecords(options);
372
+ const applied = [];
373
+ for (const record of records) {
374
+ try {
375
+ const result = await provider.upsertRecord(options.domain, record);
376
+ applied.push({
377
+ name: record.name,
378
+ type: record.type,
379
+ ok: Boolean(result.success),
380
+ message: result.message
381
+ });
382
+ } catch (error) {
383
+ applied.push({
384
+ name: record.name,
385
+ type: record.type,
386
+ ok: false,
387
+ message: error instanceof Error ? error.message : String(error)
388
+ });
389
+ }
390
+ }
391
+ return { domain: options.domain, applied, ok: applied.every((entry) => entry.ok) };
392
+ }
309
393
  // src/dns/godaddy.ts
310
394
  var GODADDY_API_URL = "https://api.godaddy.com";
311
395
  var GODADDY_OTE_API_URL = "https://api.ote-godaddy.com";
@@ -1882,4 +1966,4 @@ class DnsProviderFactory {
1882
1966
  }
1883
1967
  var dnsProviders = new DnsProviderFactory;
1884
1968
 
1885
- export { PorkbunProvider, GoDaddyProvider, CloudflareProvider, Route53Provider, UnifiedDnsValidator, createPorkbunValidator, createGoDaddyValidator, createRoute53Validator, createDnsProvider, detectDnsProvider, DnsProviderFactory, dnsProviders, ACMClient, ACMDnsValidator };
1969
+ export { PorkbunProvider, buildSpfValue, normalizeDkimKey, buildDkimValue, buildDmarcValue, buildMailDnsRecords, syncMailDns, GoDaddyProvider, CloudflareProvider, Route53Provider, UnifiedDnsValidator, createPorkbunValidator, createGoDaddyValidator, createRoute53Validator, createDnsProvider, detectDnsProvider, DnsProviderFactory, dnsProviders, ACMClient, ACMDnsValidator };
@@ -5,9 +5,9 @@ import {
5
5
  generateStaticSiteTemplate,
6
6
  invalidateCache,
7
7
  uploadStaticFiles
8
- } from "./chunk-ef2dwfrg.js";
8
+ } from "./chunk-5cz14833.js";
9
9
  import"./chunk-01d86gt1.js";
10
- import"./chunk-gttvakpv.js";
10
+ import"./chunk-6hymgy61.js";
11
11
  import"./chunk-4cjrg98a.js";
12
12
  import"./chunk-32e7ya18.js";
13
13
  import"./chunk-wj3s95p9.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  deployStaticSiteWithExternalDnsFull
3
- } from "./chunk-ef2dwfrg.js";
3
+ } from "./chunk-5cz14833.js";
4
4
  import {
5
5
  box,
6
6
  error,
@@ -30,7 +30,7 @@ import {
30
30
  synchronizeDashboardUsers,
31
31
  trackDashboardOperation,
32
32
  verifyStaticApiOrigin
33
- } from "../chunk-vkd2y0fs.js";
33
+ } from "../chunk-gtz4jar2.js";
34
34
  import {
35
35
  deleteStaticSite,
36
36
  deployStaticSite,
@@ -41,7 +41,7 @@ import {
41
41
  generateStaticSiteTemplate,
42
42
  invalidateCache,
43
43
  uploadStaticFiles
44
- } from "../chunk-ef2dwfrg.js";
44
+ } from "../chunk-5cz14833.js";
45
45
  import {
46
46
  buildAndPushServerlessImage
47
47
  } from "../chunk-3g4r09dd.js";
@@ -49,7 +49,7 @@ import"../chunk-ybcz6sxc.js";
49
49
  import"../chunk-01d86gt1.js";
50
50
  import"../chunk-50jpda9q.js";
51
51
  import"../chunk-he9a874b.js";
52
- import"../chunk-gttvakpv.js";
52
+ import"../chunk-6hymgy61.js";
53
53
  import {
54
54
  IPV6_EXCLUDED_HOST_LABELS,
55
55
  MANAGEMENT_DASHBOARD_SITE,
@@ -4,6 +4,8 @@
4
4
  */
5
5
  export * from './types';
6
6
  export { PorkbunProvider } from './porkbun';
7
+ export { buildDkimValue, buildDmarcValue, buildMailDnsRecords, buildSpfValue, normalizeDkimKey, syncMailDns, } from './mail-records';
8
+ export type { MailDnsOptions, MailDnsSyncResult } from './mail-records';
7
9
  export { GoDaddyProvider } from './godaddy';
8
10
  export { CloudflareProvider } from './cloudflare';
9
11
  export { Route53Provider } from './route53-adapter';
package/dist/dns/index.js CHANGED
@@ -5,23 +5,35 @@ import {
5
5
  PorkbunProvider,
6
6
  Route53Provider,
7
7
  UnifiedDnsValidator,
8
+ buildDkimValue,
9
+ buildDmarcValue,
10
+ buildMailDnsRecords,
11
+ buildSpfValue,
8
12
  createDnsProvider,
9
13
  createGoDaddyValidator,
10
14
  createPorkbunValidator,
11
15
  createRoute53Validator,
12
16
  detectDnsProvider,
13
- dnsProviders
14
- } from "../chunk-gttvakpv.js";
17
+ dnsProviders,
18
+ normalizeDkimKey,
19
+ syncMailDns
20
+ } from "../chunk-6hymgy61.js";
15
21
  import"../chunk-32e7ya18.js";
16
22
  import"../chunk-zqtpg06c.js";
17
23
  import"../chunk-v0bahtg2.js";
18
24
  export {
25
+ syncMailDns,
26
+ normalizeDkimKey,
19
27
  dnsProviders,
20
28
  detectDnsProvider,
21
29
  createRoute53Validator,
22
30
  createPorkbunValidator,
23
31
  createGoDaddyValidator,
24
32
  createDnsProvider,
33
+ buildSpfValue,
34
+ buildMailDnsRecords,
35
+ buildDmarcValue,
36
+ buildDkimValue,
25
37
  UnifiedDnsValidator,
26
38
  Route53Provider,
27
39
  PorkbunProvider,
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Mail DNS provisioning.
3
+ *
4
+ * A domain that sends mail needs four records, and getting any one of them
5
+ * wrong is not a visible error: mail simply arrives in spam, or is silently
6
+ * rejected by the receiving side. That failure mode is why this belongs in the
7
+ * deploy rather than in a runbook — a deploy that stands up a mail-sending app
8
+ * and leaves its DNS to be typed by hand has not finished the job.
9
+ *
10
+ * The record set is deliberately a pure function of its inputs, so what a
11
+ * deploy is about to publish can be inspected, diffed and tested without an
12
+ * API call or a live zone.
13
+ *
14
+ * @module ts-cloud/dns/mail-records
15
+ */
16
+ import type { DnsProvider, DnsRecord } from './types';
17
+ export interface MailDnsOptions {
18
+ /** The domain that sends mail, e.g. `example.com`. */
19
+ domain: string;
20
+ /** Hostname of the mail server that receives for it. */
21
+ mailHost: string;
22
+ /** Public IPv4 of the sending server, authorised in SPF. */
23
+ ip?: string;
24
+ /** Additional SPF mechanisms, e.g. `include:amazonses.com`. */
25
+ spfIncludes?: string[];
26
+ /** DKIM selector. Convention is `default`. */
27
+ dkimSelector?: string;
28
+ /**
29
+ * DKIM public key, base64, without PEM armour or newlines. Omit to skip the
30
+ * DKIM record: publishing an empty or malformed key is worse than publishing
31
+ * none, because receivers treat a broken signature as a stronger negative
32
+ * signal than an unsigned message.
33
+ */
34
+ dkimPublicKey?: string;
35
+ /** MX preference. */
36
+ mxPriority?: number;
37
+ /**
38
+ * DMARC policy. `none` by default: it asks receivers to report rather than
39
+ * to reject, which is the only safe setting to switch on automatically for a
40
+ * domain whose mail history nobody has checked yet.
41
+ */
42
+ dmarcPolicy?: 'none' | 'quarantine' | 'reject';
43
+ /** Where aggregate DMARC reports go. Omitted from the record when absent. */
44
+ dmarcReportTo?: string;
45
+ ttl?: number;
46
+ }
47
+ /** SPF is a single TXT record; more than one is a permanent error. */
48
+ export declare function buildSpfValue(options: Pick<MailDnsOptions, 'ip' | 'spfIncludes'>): string;
49
+ /** Strip PEM armour and whitespace, which a DKIM TXT record must not contain. */
50
+ export declare function normalizeDkimKey(key: string): string;
51
+ export declare function buildDkimValue(publicKey: string): string;
52
+ export declare function buildDmarcValue(options: Pick<MailDnsOptions, 'dmarcPolicy' | 'dmarcReportTo'>): string;
53
+ /**
54
+ * The full record set a mail-sending domain needs.
55
+ *
56
+ * Names are returned as the labels providers expect (`@` for the apex), since
57
+ * every provider in this package normalises from that form.
58
+ */
59
+ export declare function buildMailDnsRecords(options: MailDnsOptions): DnsRecord[];
60
+ export interface MailDnsSyncResult {
61
+ domain: string;
62
+ applied: Array<{
63
+ name: string;
64
+ type: string;
65
+ ok: boolean;
66
+ message?: string;
67
+ }>;
68
+ /** True when every record was written. */
69
+ ok: boolean;
70
+ }
71
+ /**
72
+ * Publish the record set, idempotently.
73
+ *
74
+ * Uses `upsertRecord` rather than create, so a redeploy converges instead of
75
+ * accumulating duplicate SPF records — two SPF TXT records on one domain is a
76
+ * permanent error under RFC 7208 and breaks mail that previously worked.
77
+ *
78
+ * Never throws. Mail DNS is one part of a deploy, and a zone that is
79
+ * momentarily unreachable should surface as a reported failure rather than
80
+ * roll back an otherwise healthy release.
81
+ */
82
+ export declare function syncMailDns(provider: DnsProvider, options: MailDnsOptions): Promise<MailDnsSyncResult>;
package/dist/index.d.ts CHANGED
@@ -37,7 +37,8 @@ export { createCloudDriver, CloudDriverFactory, cloudDrivers, AwsDriver, Hetzner
37
37
  export type { CreateCloudDriverOptions } from './drivers/factory';
38
38
  export { dashboardActions, resolveDashboardAction, sanitizeCloudConfig, startLocalDashboardServer, } from './deploy/local-dashboard-server';
39
39
  export type { DashboardAction, LocalDashboardServer, LocalDashboardServerOptions, } from './deploy/local-dashboard-server';
40
- export { createDnsProvider, detectDnsProvider, DnsProviderFactory, dnsProviders, PorkbunProvider, GoDaddyProvider, Route53Provider, UnifiedDnsValidator, createPorkbunValidator, createGoDaddyValidator, createRoute53Validator, } from './dns';
40
+ export { createDnsProvider, detectDnsProvider, DnsProviderFactory, dnsProviders, PorkbunProvider, GoDaddyProvider, Route53Provider, UnifiedDnsValidator, createPorkbunValidator, createGoDaddyValidator, createRoute53Validator, buildMailDnsRecords, buildSpfValue, buildDkimValue, buildDmarcValue, normalizeDkimKey, syncMailDns, } from './dns';
41
+ export type { MailDnsOptions, MailDnsSyncResult } from './dns';
41
42
  export * from './source';
42
43
  export * from './queue';
43
44
  export * from './backups';
package/dist/index.js CHANGED
@@ -283,7 +283,7 @@ import {
283
283
  volumeCapabilities,
284
284
  webhookEndpoint,
285
285
  zeroCapacity
286
- } from "./chunk-vkd2y0fs.js";
286
+ } from "./chunk-gtz4jar2.js";
287
287
  import {
288
288
  deleteStaticSite,
289
289
  deployStaticSite,
@@ -294,7 +294,7 @@ import {
294
294
  generateStaticSiteTemplate,
295
295
  invalidateCache,
296
296
  uploadStaticFiles
297
- } from "./chunk-ef2dwfrg.js";
297
+ } from "./chunk-5cz14833.js";
298
298
  import {
299
299
  buildAndPushServerlessImage
300
300
  } from "./chunk-3g4r09dd.js";
@@ -353,13 +353,19 @@ import {
353
353
  PorkbunProvider,
354
354
  Route53Provider,
355
355
  UnifiedDnsValidator,
356
+ buildDkimValue,
357
+ buildDmarcValue,
358
+ buildMailDnsRecords,
359
+ buildSpfValue,
356
360
  createDnsProvider,
357
361
  createGoDaddyValidator,
358
362
  createPorkbunValidator,
359
363
  createRoute53Validator,
360
364
  detectDnsProvider,
361
- dnsProviders
362
- } from "./chunk-gttvakpv.js";
365
+ dnsProviders,
366
+ normalizeDkimKey,
367
+ syncMailDns
368
+ } from "./chunk-6hymgy61.js";
363
369
  import {
364
370
  AwsDriver,
365
371
  CloudDriverFactory,
@@ -5163,6 +5169,7 @@ export {
5163
5169
  synchronizeConfiguredConfiguration,
5164
5170
  synchronizeComposeVolumes,
5165
5171
  syncSourceRepositories,
5172
+ syncMailDns,
5166
5173
  suggestRegions,
5167
5174
  suggestRegionPairs,
5168
5175
  suggestQuotaIncrease,
@@ -5313,6 +5320,7 @@ export {
5313
5320
  normalizeScheduleExpression,
5314
5321
  normalizeRuntimeStatus,
5315
5322
  normalizePublicIpv6,
5323
+ normalizeDkimKey,
5316
5324
  nextScheduleRuns,
5317
5325
  networkSecurityManager,
5318
5326
  needsRenewal,
@@ -5586,14 +5594,18 @@ export {
5586
5594
  bytes,
5587
5595
  buildStaticSiteDeployScript,
5588
5596
  buildSshArgs,
5597
+ buildSpfValue,
5589
5598
  buildSiteDeployScript,
5590
5599
  buildPhpRuntimeLayerZip,
5591
5600
  buildOptimizationManager,
5592
5601
  buildNodeRuntimeLayerZip,
5593
5602
  buildMediaCdnPlan,
5594
5603
  buildManagementDashboardArtifact,
5604
+ buildMailDnsRecords,
5595
5605
  buildHostCleanupScript,
5596
5606
  buildFunctionEnv,
5607
+ buildDmarcValue,
5608
+ buildDkimValue,
5597
5609
  buildComposeShellCommand,
5598
5610
  buildComposeScaleCommand,
5599
5611
  buildComposeRuntimeCommand,