@amerged/ohmyhost-cli 0.1.35 → 0.1.37
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.
- package/README.md +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-ZQSLRNH6.js → chunk-IHXNADOQ.js} +1145 -226
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +37 -1
- package/src/apps/product-cli/src/command.ts +228 -2
- package/src/apps/product-cli/src/composition.ts +4 -0
- package/src/apps/product-cli/src/product-api.ts +11 -1
- package/src/packages/contracts/package.json +5 -0
- package/src/packages/contracts/src/operation-failure.ts +4 -0
- package/src/packages/contracts/src/problem-policy.ts +2 -2
- package/src/packages/contracts/src/shared-mail.ts +236 -0
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/index.ts +112 -0
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +870 -0
- package/src/packages/sdk-ts/src/generated/shared-mail-response.ts +238 -0
- package/src/packages/sdk-ts/src/generated/types.gen.ts +1208 -0
- package/src/packages/sdk-ts/src/index.ts +2 -0
- package/src/packages/sdk-ts/src/shared-mail-response.ts +1 -0
- package/src/packages/sdk-ts/src/shared-mail.ts +225 -0
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -470,6 +470,37 @@ const HELP_USAGE = Object.freeze({
|
|
|
470
470
|
"printf '%s' \"$SECRET_VALUE\" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--profile-user USER_ID --profile-organization ULID | --token-user USER_ID --token-organization ULID] --stdin [--wait] --json (with --profile-user and --profile-organization the saved login that runs it must belong to that user and organization; with --token-user and --token-organization it runs only with an OHMYHOST_TOKEN of that user and organization, never with a saved login)",
|
|
471
471
|
"secret delete":
|
|
472
472
|
"ohmyhost secret delete NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--wait] --json",
|
|
473
|
+
"mail workspace list": "ohmyhost mail workspace list --organization ULID --json",
|
|
474
|
+
"mail workspace create":
|
|
475
|
+
"ohmyhost mail workspace create --organization ULID --domain DOMAIN --sending true --idempotency-key KEY --json",
|
|
476
|
+
"mail workspace status":
|
|
477
|
+
"ohmyhost mail workspace status --organization ULID --mail-domain ULID --json",
|
|
478
|
+
"mail workspace retire":
|
|
479
|
+
"ohmyhost mail workspace retire --organization ULID --mail-domain ULID --expected-revision N --idempotency-key KEY --yes --json",
|
|
480
|
+
"mail workspace dns-authorize":
|
|
481
|
+
"ohmyhost mail workspace dns-authorize --organization ULID --mail-domain ULID --expected-revision N --zone DOMAIN --idempotency-key KEY --json",
|
|
482
|
+
"mail workspace dns-revoke":
|
|
483
|
+
"ohmyhost mail workspace dns-revoke --organization ULID --mail-domain ULID --expected-revision N --idempotency-key KEY --yes --json",
|
|
484
|
+
"mail workspace dns-status":
|
|
485
|
+
"ohmyhost mail workspace dns-status --organization ULID --mail-domain ULID --json",
|
|
486
|
+
"mail binding get": "ohmyhost mail binding get --project ULID --environment PROD_ULID --json",
|
|
487
|
+
"mail binding set":
|
|
488
|
+
"ohmyhost mail binding set --project ULID --environment PROD_ULID --mail-domain ULID --sending true --sender-addresses contact@mail.example.com,contracts@mail.example.com --default-from contracts@mail.example.com [--reply-to owner@example.com] --expected-revision N --idempotency-key KEY --json",
|
|
489
|
+
"mail binding detach":
|
|
490
|
+
"ohmyhost mail binding detach --project ULID --environment PROD_ULID --expected-revision N --idempotency-key KEY --yes --json",
|
|
491
|
+
"mail identity get": "ohmyhost mail identity get --project ULID --json",
|
|
492
|
+
"mail identity declare":
|
|
493
|
+
"ohmyhost mail identity declare --project ULID --hostname sign.example.com --idempotency-key KEY --json",
|
|
494
|
+
"mail identity verify":
|
|
495
|
+
"ohmyhost mail identity verify --project ULID --expected-revision N --idempotency-key KEY --json",
|
|
496
|
+
"mail identity revoke":
|
|
497
|
+
"ohmyhost mail identity revoke --project ULID --expected-revision N --idempotency-key KEY --yes --json",
|
|
498
|
+
"mail identity authorize":
|
|
499
|
+
"ohmyhost mail identity authorize --project ULID --expected-revision N --zone example.com --idempotency-key KEY --json",
|
|
500
|
+
"mail identity authorization-revoke":
|
|
501
|
+
"ohmyhost mail identity authorization-revoke --project ULID --expected-revision N --idempotency-key KEY --yes --json",
|
|
502
|
+
"mail identity authorization-status":
|
|
503
|
+
"ohmyhost mail identity authorization-status --project ULID --json",
|
|
473
504
|
"mail setup":
|
|
474
505
|
"ohmyhost mail setup --project ULID --environment ULID --domain DOMAIN --sending true --receiving false --idempotency-key KEY --json",
|
|
475
506
|
"mail status": "ohmyhost mail status --project ULID --environment ULID --json",
|
|
@@ -1114,6 +1145,11 @@ export class ProductCli {
|
|
|
1114
1145
|
if (command.kind === "secret-list") return await this.listEnvironmentSecrets(command, signal);
|
|
1115
1146
|
if (command.kind === "function-runs") return await this.listFunctionRuns(command, signal);
|
|
1116
1147
|
if (command.kind === "secret-set") return await this.putEnvironmentSecret(command, signal);
|
|
1148
|
+
if (command.kind === "shared-mail") {
|
|
1149
|
+
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1150
|
+
if (!api.sharedMail) throw new Error("Shared mail unavailable");
|
|
1151
|
+
return success(command.label, { mail: await api.sharedMail(command.request) });
|
|
1152
|
+
}
|
|
1117
1153
|
if (command.kind === "managed-mail") {
|
|
1118
1154
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
1119
1155
|
if (!api.managedMail) throw new Error("Mail unavailable");
|
|
@@ -3120,7 +3156,7 @@ const parsedCommandName = (command: ProductCliCommand): CommandLabel => {
|
|
|
3120
3156
|
if (command.kind === "function-runs") return "function runs";
|
|
3121
3157
|
if (command.kind === "secret-set") return "secret set";
|
|
3122
3158
|
if (command.kind === "secret-delete") return "secret delete";
|
|
3123
|
-
if (command.kind === "managed-mail") return command.label;
|
|
3159
|
+
if (command.kind === "shared-mail" || command.kind === "managed-mail") return command.label;
|
|
3124
3160
|
if (command.kind === "profile-list") return "profile list";
|
|
3125
3161
|
return command.kind;
|
|
3126
3162
|
};
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
isProjectDataChangeKind,
|
|
4
4
|
type ProjectDataChangeKind,
|
|
5
5
|
} from "@ohmyhost/contracts/project-data-changes";
|
|
6
|
-
import type { ManagedMailCommand } from "@ohmyhost/sdk-ts";
|
|
6
|
+
import type { ManagedMailCommand, SharedMailCommand } from "@ohmyhost/sdk-ts";
|
|
7
7
|
import { USER_API_KEY_ID } from "@ohmyhost/contracts/user-api-keys";
|
|
8
8
|
import { WORKOS_USER_API_KEY_PATTERN } from "@ohmyhost/workos-auth-contracts/user-api-keys";
|
|
9
9
|
import { isProfileName, isProfileUserId } from "./profile-store.js";
|
|
@@ -536,6 +536,12 @@ export type ProductCliCommand =
|
|
|
536
536
|
readonly wait: boolean;
|
|
537
537
|
readonly credentialStore: "native";
|
|
538
538
|
}
|
|
539
|
+
| {
|
|
540
|
+
readonly kind: "shared-mail";
|
|
541
|
+
readonly request: SharedMailCommand;
|
|
542
|
+
readonly label: SharedMailCommandLabel;
|
|
543
|
+
readonly credentialStore: "native";
|
|
544
|
+
}
|
|
539
545
|
| {
|
|
540
546
|
readonly kind: "managed-mail";
|
|
541
547
|
readonly request: ManagedMailCommand;
|
|
@@ -902,7 +908,27 @@ export type RecognizedCommandLabel =
|
|
|
902
908
|
| "mail messages retry"
|
|
903
909
|
| "mail domain set"
|
|
904
910
|
| "mail domain status"
|
|
905
|
-
| "mail domain delete"
|
|
911
|
+
| "mail domain delete"
|
|
912
|
+
| SharedMailCommandLabel;
|
|
913
|
+
|
|
914
|
+
export type SharedMailCommandLabel =
|
|
915
|
+
| "mail workspace list"
|
|
916
|
+
| "mail workspace create"
|
|
917
|
+
| "mail workspace status"
|
|
918
|
+
| "mail workspace retire"
|
|
919
|
+
| "mail workspace dns-authorize"
|
|
920
|
+
| "mail workspace dns-status"
|
|
921
|
+
| "mail workspace dns-revoke"
|
|
922
|
+
| "mail binding get"
|
|
923
|
+
| "mail binding set"
|
|
924
|
+
| "mail binding detach"
|
|
925
|
+
| "mail identity get"
|
|
926
|
+
| "mail identity declare"
|
|
927
|
+
| "mail identity verify"
|
|
928
|
+
| "mail identity revoke"
|
|
929
|
+
| "mail identity authorize"
|
|
930
|
+
| "mail identity authorization-status"
|
|
931
|
+
| "mail identity authorization-revoke";
|
|
906
932
|
|
|
907
933
|
export const recognizedCommandLabel = (argv: readonly string[]): RecognizedCommandLabel => {
|
|
908
934
|
const values = [...argv];
|
|
@@ -1052,6 +1078,11 @@ export const recognizedCommandLabel = (argv: readonly string[]): RecognizedComma
|
|
|
1052
1078
|
}
|
|
1053
1079
|
if (value === "function" && values[0] === "runs") return "function runs";
|
|
1054
1080
|
if (value === "mail") {
|
|
1081
|
+
if (["workspace", "binding", "identity"].includes(values[0] ?? "")) {
|
|
1082
|
+
const candidate = `mail ${values[0]} ${values[1]}`;
|
|
1083
|
+
if (SHARED_MAIL_LABELS.includes(candidate as SharedMailCommandLabel))
|
|
1084
|
+
return candidate as SharedMailCommandLabel;
|
|
1085
|
+
}
|
|
1055
1086
|
if (values[0] === "setup") return "mail setup";
|
|
1056
1087
|
if (values[0] === "status") return "mail status";
|
|
1057
1088
|
if (values[0] === "webhook") {
|
|
@@ -2328,6 +2359,10 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
2328
2359
|
}
|
|
2329
2360
|
throw new InvalidCommandError();
|
|
2330
2361
|
}
|
|
2362
|
+
if (first === "mail" && ["workspace", "binding", "identity"].includes(values[0] ?? "")) {
|
|
2363
|
+
if (wait || follow || stdin) throw new InvalidCommandError();
|
|
2364
|
+
return parseSharedMailCommand(values, yes);
|
|
2365
|
+
}
|
|
2331
2366
|
if (first === "mail") {
|
|
2332
2367
|
const area = values.shift();
|
|
2333
2368
|
const sub =
|
|
@@ -2538,3 +2573,194 @@ const validPaidHostname = (value: string): boolean =>
|
|
|
2538
2573
|
!value.endsWith(".omh.st") &&
|
|
2539
2574
|
value !== "ohmyho.st" &&
|
|
2540
2575
|
!value.endsWith(".ohmyho.st");
|
|
2576
|
+
|
|
2577
|
+
const SHARED_MAIL_LABELS: readonly SharedMailCommandLabel[] = [
|
|
2578
|
+
"mail workspace list",
|
|
2579
|
+
"mail workspace create",
|
|
2580
|
+
"mail workspace status",
|
|
2581
|
+
"mail workspace retire",
|
|
2582
|
+
"mail workspace dns-authorize",
|
|
2583
|
+
"mail workspace dns-status",
|
|
2584
|
+
"mail workspace dns-revoke",
|
|
2585
|
+
"mail binding get",
|
|
2586
|
+
"mail binding set",
|
|
2587
|
+
"mail binding detach",
|
|
2588
|
+
"mail identity get",
|
|
2589
|
+
"mail identity declare",
|
|
2590
|
+
"mail identity verify",
|
|
2591
|
+
"mail identity revoke",
|
|
2592
|
+
"mail identity authorize",
|
|
2593
|
+
"mail identity authorization-status",
|
|
2594
|
+
"mail identity authorization-revoke",
|
|
2595
|
+
];
|
|
2596
|
+
|
|
2597
|
+
/** New workspace sender operations stay separate from the exact legacy project mail contract. */
|
|
2598
|
+
function parseSharedMailCommand(values: string[], yes: boolean): ProductCliCommand {
|
|
2599
|
+
const area = values.shift(),
|
|
2600
|
+
operation = values.shift();
|
|
2601
|
+
const label = `mail ${area} ${operation}` as SharedMailCommandLabel;
|
|
2602
|
+
if (!SHARED_MAIL_LABELS.includes(label)) throw new InvalidCommandError();
|
|
2603
|
+
const destructive =
|
|
2604
|
+
operation === "retire" ||
|
|
2605
|
+
operation === "detach" ||
|
|
2606
|
+
operation === "revoke" ||
|
|
2607
|
+
operation === "dns-revoke" ||
|
|
2608
|
+
operation === "authorization-revoke";
|
|
2609
|
+
if (yes !== destructive) throw new InvalidCommandError();
|
|
2610
|
+
const allowed = area === "workspace" ? ["--organization"] : ["--project"];
|
|
2611
|
+
const writing = [
|
|
2612
|
+
"create",
|
|
2613
|
+
"retire",
|
|
2614
|
+
"dns-authorize",
|
|
2615
|
+
"dns-revoke",
|
|
2616
|
+
"set",
|
|
2617
|
+
"detach",
|
|
2618
|
+
"declare",
|
|
2619
|
+
"verify",
|
|
2620
|
+
"revoke",
|
|
2621
|
+
"authorize",
|
|
2622
|
+
"authorization-revoke",
|
|
2623
|
+
].includes(operation ?? "");
|
|
2624
|
+
if (area === "workspace" && operation !== "list" && operation !== "create")
|
|
2625
|
+
allowed.push("--mail-domain");
|
|
2626
|
+
if (area === "binding") allowed.push("--environment");
|
|
2627
|
+
if (operation === "create") allowed.push("--domain", "--sending");
|
|
2628
|
+
if (area === "binding" && operation === "set")
|
|
2629
|
+
allowed.push(
|
|
2630
|
+
"--mail-domain",
|
|
2631
|
+
"--sending",
|
|
2632
|
+
"--sender-addresses",
|
|
2633
|
+
"--default-from",
|
|
2634
|
+
"--reply-to",
|
|
2635
|
+
);
|
|
2636
|
+
if (operation === "declare") allowed.push("--hostname");
|
|
2637
|
+
if (operation === "authorize" || operation === "dns-authorize") allowed.push("--zone");
|
|
2638
|
+
if (writing) allowed.push("--idempotency-key");
|
|
2639
|
+
if (writing && operation !== "create" && operation !== "declare")
|
|
2640
|
+
allowed.push("--expected-revision");
|
|
2641
|
+
const options = parseOptionalOptions(values, allowed);
|
|
2642
|
+
const required = (key: keyof typeof options) => {
|
|
2643
|
+
const value = options[key];
|
|
2644
|
+
if (!value) throw new InvalidCommandError();
|
|
2645
|
+
return value;
|
|
2646
|
+
};
|
|
2647
|
+
const revision = () => {
|
|
2648
|
+
const value = required("--expected-revision");
|
|
2649
|
+
if (!/^(?:0|[1-9][0-9]*)$/u.test(value) || !Number.isSafeInteger(Number(value)))
|
|
2650
|
+
throw new InvalidCommandError();
|
|
2651
|
+
return Number(value);
|
|
2652
|
+
};
|
|
2653
|
+
const sending = () => {
|
|
2654
|
+
const value = required("--sending");
|
|
2655
|
+
if (value !== "true" && value !== "false") throw new InvalidCommandError();
|
|
2656
|
+
return value === "true";
|
|
2657
|
+
};
|
|
2658
|
+
const idempotencyKey = () => required("--idempotency-key");
|
|
2659
|
+
let request: SharedMailCommand;
|
|
2660
|
+
if (area === "workspace") {
|
|
2661
|
+
const scope = { organizationId: required("--organization") };
|
|
2662
|
+
if (operation === "list") request = { ...scope, action: "domains_list" };
|
|
2663
|
+
else if (operation === "create") {
|
|
2664
|
+
const enabled = sending();
|
|
2665
|
+
if (!enabled) throw new InvalidCommandError();
|
|
2666
|
+
request = {
|
|
2667
|
+
...scope,
|
|
2668
|
+
action: "domain_create",
|
|
2669
|
+
domain: required("--domain"),
|
|
2670
|
+
sending: enabled,
|
|
2671
|
+
idempotencyKey: idempotencyKey(),
|
|
2672
|
+
};
|
|
2673
|
+
} else {
|
|
2674
|
+
const target = { ...scope, mailDomainId: required("--mail-domain") };
|
|
2675
|
+
if (operation === "status") request = { ...target, action: "domain_get" };
|
|
2676
|
+
else if (operation === "dns-status") request = { ...target, action: "domain_dns_status" };
|
|
2677
|
+
else if (operation === "dns-revoke")
|
|
2678
|
+
request = {
|
|
2679
|
+
...target,
|
|
2680
|
+
action: "domain_dns_revoke",
|
|
2681
|
+
expectedRevision: revision(),
|
|
2682
|
+
idempotencyKey: idempotencyKey(),
|
|
2683
|
+
};
|
|
2684
|
+
else if (operation === "retire")
|
|
2685
|
+
request = {
|
|
2686
|
+
...target,
|
|
2687
|
+
action: "domain_retire",
|
|
2688
|
+
expectedRevision: revision(),
|
|
2689
|
+
idempotencyKey: idempotencyKey(),
|
|
2690
|
+
};
|
|
2691
|
+
else
|
|
2692
|
+
request = {
|
|
2693
|
+
...target,
|
|
2694
|
+
action: "domain_dns_authorize",
|
|
2695
|
+
expectedRevision: revision(),
|
|
2696
|
+
zone: required("--zone"),
|
|
2697
|
+
idempotencyKey: idempotencyKey(),
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
} else if (area === "binding") {
|
|
2701
|
+
const scope = { projectId: required("--project"), environmentId: required("--environment") };
|
|
2702
|
+
if (operation === "get") request = { ...scope, action: "binding_get" };
|
|
2703
|
+
else if (operation === "detach")
|
|
2704
|
+
request = {
|
|
2705
|
+
...scope,
|
|
2706
|
+
action: "binding_detach",
|
|
2707
|
+
expectedRevision: revision(),
|
|
2708
|
+
idempotencyKey: idempotencyKey(),
|
|
2709
|
+
};
|
|
2710
|
+
else {
|
|
2711
|
+
const senderAddresses = required("--sender-addresses").split(",");
|
|
2712
|
+
if (
|
|
2713
|
+
senderAddresses.length > 32 ||
|
|
2714
|
+
senderAddresses.some((address) => !address || address.trim() !== address) ||
|
|
2715
|
+
new Set(senderAddresses).size !== senderAddresses.length
|
|
2716
|
+
)
|
|
2717
|
+
throw new InvalidCommandError();
|
|
2718
|
+
request = {
|
|
2719
|
+
...scope,
|
|
2720
|
+
action: "binding_set",
|
|
2721
|
+
mailDomainId: required("--mail-domain"),
|
|
2722
|
+
sending: sending(),
|
|
2723
|
+
senderAddresses,
|
|
2724
|
+
defaultFrom: required("--default-from"),
|
|
2725
|
+
defaultReplyTo: options["--reply-to"] ?? null,
|
|
2726
|
+
expectedRevision: revision(),
|
|
2727
|
+
idempotencyKey: idempotencyKey(),
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
} else {
|
|
2731
|
+
const scope = { projectId: required("--project") };
|
|
2732
|
+
if (operation === "get") request = { ...scope, action: "identity_get" };
|
|
2733
|
+
else if (operation === "authorization-status")
|
|
2734
|
+
request = { ...scope, action: "identity_authorization_status" };
|
|
2735
|
+
else if (operation === "authorization-revoke")
|
|
2736
|
+
request = {
|
|
2737
|
+
...scope,
|
|
2738
|
+
action: "identity_authorization_revoke",
|
|
2739
|
+
expectedRevision: revision(),
|
|
2740
|
+
idempotencyKey: idempotencyKey(),
|
|
2741
|
+
};
|
|
2742
|
+
else if (operation === "declare")
|
|
2743
|
+
request = {
|
|
2744
|
+
...scope,
|
|
2745
|
+
action: "identity_declare",
|
|
2746
|
+
hostname: required("--hostname"),
|
|
2747
|
+
idempotencyKey: idempotencyKey(),
|
|
2748
|
+
};
|
|
2749
|
+
else if (operation === "authorize")
|
|
2750
|
+
request = {
|
|
2751
|
+
...scope,
|
|
2752
|
+
action: "identity_authorize",
|
|
2753
|
+
zone: required("--zone"),
|
|
2754
|
+
expectedRevision: revision(),
|
|
2755
|
+
idempotencyKey: idempotencyKey(),
|
|
2756
|
+
};
|
|
2757
|
+
else
|
|
2758
|
+
request = {
|
|
2759
|
+
...scope,
|
|
2760
|
+
action: operation === "verify" ? "identity_verify" : "identity_revoke",
|
|
2761
|
+
expectedRevision: revision(),
|
|
2762
|
+
idempotencyKey: idempotencyKey(),
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
return { kind: "shared-mail", request, label, credentialStore: "native" };
|
|
2766
|
+
}
|
|
@@ -528,6 +528,8 @@ const readTokenIdentity = async (input: {
|
|
|
528
528
|
/** The organization a command names explicitly; `organization use` names its target instead. */
|
|
529
529
|
const commandOrganizationId = (command: ProductCliCommand): string | undefined => {
|
|
530
530
|
if (command.kind === "organization-use" || command.kind === "login") return undefined;
|
|
531
|
+
if (command.kind === "shared-mail" && "organizationId" in command.request)
|
|
532
|
+
return command.request.organizationId;
|
|
531
533
|
if (command.kind === "feedback-submit") return command.report.organization_id;
|
|
532
534
|
return "organizationId" in command && typeof command.organizationId === "string"
|
|
533
535
|
? command.organizationId
|
|
@@ -535,6 +537,8 @@ const commandOrganizationId = (command: ProductCliCommand): string | undefined =
|
|
|
535
537
|
};
|
|
536
538
|
|
|
537
539
|
const commandProjectId = (command: ProductCliCommand): string | undefined => {
|
|
540
|
+
if (command.kind === "shared-mail")
|
|
541
|
+
return "projectId" in command.request ? command.request.projectId : undefined;
|
|
538
542
|
if (command.kind === "managed-mail") return command.request.projectId;
|
|
539
543
|
return "projectId" in command && typeof command.projectId === "string"
|
|
540
544
|
? command.projectId
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
executeManagedMail,
|
|
3
|
+
executeSharedMail,
|
|
4
|
+
type ManagedMailCommand,
|
|
5
|
+
type SharedMailCommand,
|
|
6
|
+
} from "@ohmyhost/sdk-ts";
|
|
2
7
|
import type {
|
|
3
8
|
ProjectDataChangeKind,
|
|
4
9
|
ProjectDataChangePlan,
|
|
@@ -434,6 +439,7 @@ export interface ProductApi {
|
|
|
434
439
|
readonly name: string;
|
|
435
440
|
readonly idempotencyKey: string;
|
|
436
441
|
}): Promise<DeleteEnvironmentSecretResult>;
|
|
442
|
+
sharedMail?(input: SharedMailCommand): Promise<unknown>;
|
|
437
443
|
managedMail?(input: ManagedMailCommand): Promise<unknown>;
|
|
438
444
|
}
|
|
439
445
|
|
|
@@ -1237,6 +1243,10 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
1237
1243
|
);
|
|
1238
1244
|
}
|
|
1239
1245
|
|
|
1246
|
+
public sharedMail(input: SharedMailCommand) {
|
|
1247
|
+
return executeSharedMail(this.#client, input);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1240
1250
|
public managedMail(input: ManagedMailCommand) {
|
|
1241
1251
|
return executeManagedMail(this.#client, input);
|
|
1242
1252
|
}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"exports": {
|
|
8
|
+
"./shared-mail": {
|
|
9
|
+
"source": "./src/shared-mail.ts",
|
|
10
|
+
"types": "./dist/shared-mail.d.ts",
|
|
11
|
+
"import": "./dist/shared-mail.js"
|
|
12
|
+
},
|
|
8
13
|
"./mcp-source-codec": {
|
|
9
14
|
"source": "./src/mcp-source-codec.ts",
|
|
10
15
|
"types": "./dist/mcp-source-codec.d.ts",
|
|
@@ -90,6 +90,10 @@ const failures = {
|
|
|
90
90
|
"The organization does not have sufficient available credits for this operation.",
|
|
91
91
|
"Ask the organization owner to top up credits, then create a new deployment plan. Preserve existing data; do not buy a second subscription or repeatedly reconcile this terminal operation.",
|
|
92
92
|
],
|
|
93
|
+
project_budget_exceeded: [
|
|
94
|
+
"The project's Stop budget prevents this deployment.",
|
|
95
|
+
"This project's Stop budget for the current UTC month was reached; no build started. Read 'ohmyhost budget get --project ULID --json'. Ask the organization Owner to change the limit or mode only if they want to allow more spending; otherwise wait for the next UTC month. Then plan and deploy again or send a new push. Replaying this terminal operation cannot start a build.",
|
|
96
|
+
],
|
|
93
97
|
paid_plan_required: [
|
|
94
98
|
"Transactional mail requires an active Paid plan for this organization.",
|
|
95
99
|
"Ask the organization Owner to activate Paid through billing checkout; top-ups and signup credits do not activate it. Then plan the same deployment or promotion again. If the app should send no mail, instead set mail.enabled to false in ohmyhost.yaml, save or push the corrected version and plan its commit. Replaying this operation cannot enable mail. Do not reset the database.",
|
|
@@ -313,14 +313,14 @@ export const PROBLEM_POLICY = {
|
|
|
313
313
|
status: 409,
|
|
314
314
|
retryable: false,
|
|
315
315
|
action:
|
|
316
|
-
"
|
|
316
|
+
"Read the workspace sender resource and project binding. Reuse requires explicit domain-use authority, target-project editing and a current verified application identity with the same registrable main domain. Read the current revision before changing settings. Detach a shared project binding explicitly; legacy domain deletion cannot retire a resource used by another project.",
|
|
317
317
|
title: "Mail domain conflict",
|
|
318
318
|
},
|
|
319
319
|
mail_domain_required: {
|
|
320
320
|
status: 409,
|
|
321
321
|
retryable: false,
|
|
322
322
|
action:
|
|
323
|
-
"This app declares mail.enabled. Configure
|
|
323
|
+
"This app declares mail.enabled. Configure a sender with 'ohmyhost mail setup' or explicitly attach an authorized workspace sender using the project's Prod environment ID. Reuse first requires proof of the intended application hostname with the same registrable main domain; declare and verify that identity before mail-gated deployment. Then plan again.",
|
|
324
324
|
title: "Mail domain required",
|
|
325
325
|
},
|
|
326
326
|
storage_jurisdiction_conflict: {
|