posthorn 0.2.6 → 0.2.8

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 (3) hide show
  1. package/README.md +79 -63
  2. package/dist/index.js +4 -4
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -42,19 +42,63 @@ The platform is a pure orchestration layer: the USER owns their Cloudflare
42
42
  account, their Google Workspace, their domains, and their mailboxes. Posthorn
43
43
  never owns or bills for any of it.
44
44
 
45
- ## The end-to-end flow (in order)
46
-
47
- 1. Account → `posthorn auth register` (anonymous API key, instant)
48
- 2. Cloudflare → user creates account + API token, then `posthorn accounts cloudflare <token>`
49
- 3. Workspace → user sets up domain-wide delegation, then `posthorn accounts workspace <admin-email>`
50
- 4. Domain → buy new OR connect existing OR managed DNS
51
- 5. DKIM → browser step (see below)
52
- 6. Mailboxes → `posthorn mailboxes create ...`
53
- 7. Verify account `posthorn auth verify` (unlocks sending/warmup, "verified" tier)
54
- 8. Warmup → `posthorn warmup start <mailbox-id>`
45
+ ## The flow: walk it like a setup wizard
46
+
47
+ Go step by step. Ask one question at a time, only when the step needs it, and
48
+ do as much as possible yourself. Don't front-load questions.
49
+
50
+ Step 1. `posthorn auth register`. Instant API key; no email or signup info
51
+ needed, and there are no account tiers. Nothing to ask.
52
+
53
+ Step 2. Domain. Ask: "Do you need a new domain for your emails, or will you
54
+ use an existing one for sending?"
55
+ - NEW domain (the purchase always happens on the user's own Cloudflare account
56
+ and card; Posthorn never owns or bills for domains):
57
+ a. They need a Cloudflare account with a payment method (they pay Cloudflare
58
+ directly for the domain, ~$10/yr). Browser step: create the API token
59
+ (below), then `posthorn accounts cloudflare <token>`.
60
+ b. `posthorn domains check name1.com name2.io --cloudflare <id>` (availability
61
+ + price) → `posthorn domains reputation <pick>` (vets Spamhaus blocklist,
62
+ reputation score, and prior use; verdicts: clean / caution / avoid. Run it
63
+ before buying; you can't tell a tainted domain from its name.) →
64
+ `posthorn domains buy <pick> --cloudflare <id> --contact '{...}'`
65
+ - EXISTING domain. If it runs their live website or real email, recommend a
66
+ dedicated sending domain instead. Two ways to connect it; either way the
67
+ domain stays registered where they bought it, only nameservers change:
68
+ a. Their own Cloudflare: they manage the domain's DNS in their own Cloudflare
69
+ account. Needs the API token (below); and if the domain isn't on their
70
+ Cloudflare yet, they add it at dash.cloudflare.com and point nameservers
71
+ there first. Then `posthorn domains connect <domain> --cloudflare <id>`.
72
+ b. Posthorn-managed DNS: no Cloudflare account to create or manage; Posthorn
73
+ hosts the domain's DNS for them (free). `posthorn domains managed <domain>`
74
+ → they set the 2 printed nameservers at their registrar →
75
+ `posthorn domains activate <id>`. Note: Posthorn then hosts ALL of the
76
+ domain's DNS records (website records included), so it fits domains
77
+ dedicated to email.
78
+
79
+ Step 3. Google Workspace. Ask: "Do you have a Google Workspace you can add new
80
+ domains and mailboxes to, or do you want to set up a new one?"
81
+ - Existing Workspace: delegation browser step (below), then
82
+ `posthorn accounts workspace <admin-email>`.
83
+ - New Workspace: they create one at workspace.google.com using the domain from
84
+ step 2, then delegation as above.
85
+ (Delegation is per org, not per domain, so with an existing org this step can
86
+ happen any time, even before the domain exists. The domain pipeline auto-adds
87
+ and verifies the new domain inside their org.)
88
+
89
+ Step 4. Wait for the domain: poll `posthorn domains get <id>` until status
90
+ `ready` (minutes to 24h; poll every 30-60s, don't hammer). MX/SPF/DMARC are
91
+ configured automatically. Statuses progress: pending_* → purchased →
92
+ dns_configuring → dns_configured → dns_verified → workspace_verifying →
93
+ workspace_verified → ready.
94
+
95
+ Step 5. DKIM. Browser step below; once per domain, needs the domain `ready`.
96
+
97
+ Step 6. `posthorn mailboxes create <domain-id> --email ... --first ... --last ...`
98
+
99
+ Step 7. `posthorn warmup start <mailbox-id>`
55
100
 
56
101
  Dependencies: you CANNOT create a mailbox until the domain status is `ready`.
57
- You CANNOT send or start warmup until the account is "verified" tier.
58
102
 
59
103
  Run `posthorn auth status --json` any time to see where things stand. State is
60
104
  stored locally, so you can stop and continue any time.
@@ -62,15 +106,20 @@ stored locally, so you can stop and continue any time.
62
106
  ## The external/manual steps (things that happen OUTSIDE the CLI)
63
107
 
64
108
  These are the steps you must GUIDE THE USER through in their browser. Give exact
65
- click-by-click instructions. Tell the user up front that these are one-time
66
- setup steps; once done, they never repeat them. Future domains and mailboxes
67
- are fully automated (the only exceptions: DKIM is once per domain, delegation
68
- is once per Workspace org).
109
+ click-by-click instructions. Before each browser step, share with the user that
110
+ this is a one-time setup, e.g. "This is a one-time setup step; you won't need
111
+ to do this again." The repetition model, so you can answer follow-ups:
112
+ - Cloudflare API token: once ever
113
+ - Workspace delegation: once per Workspace org
114
+ - DKIM: once per domain
115
+ - Everything else (domains, mailboxes, warmup): fully automated, no browser
69
116
 
70
117
  ### Cloudflare API token (one-time, for "buy new" or "own Cloudflare" domains)
71
118
  - dash.cloudflare.com/profile/api-tokens → Create Token → Custom Token
72
119
  - Permissions: Account>Account Settings>Read, Account>Registrar: Domains>Admin,
73
- Zone>Zone>Edit, Zone>DNS>Edit. Resources: Include All.
120
+ Zone>Zone>Edit, Zone>DNS>Edit.
121
+ - Account Resources: Include > All accounts
122
+ - Zone Resources: Include > All zones
74
123
  - Do NOT add Billing permissions; they are not needed. Domain purchases charge
75
124
  the payment method already on the Cloudflare account, which is a dashboard
76
125
  setting, not a token permission.
@@ -87,7 +136,9 @@ is once per Workspace org).
87
136
  - Client ID: 110137377718772968374
88
137
  - OAuth scopes (paste all, comma-separated):
89
138
  `https://mail.google.com/,https://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.domain,https://www.googleapis.com/auth/siteverification`
90
- - Then ask for their admin email and run: `posthorn accounts workspace <admin-email>`
139
+ - Must be done signed in as a SUPER-ADMIN of that Workspace org, and the email
140
+ passed to the CLI must be that super-admin's. Then run:
141
+ `posthorn accounts workspace <admin-email>`
91
142
  - This replaces OAuth entirely: no consent screen, no app verification, no test users.
92
143
 
93
144
  ### Nameservers (only for "managed DNS" or moving a domain to Cloudflare)
@@ -109,37 +160,6 @@ If you have browser-automation tools, do it for the user:
109
160
  If no browser tools: have the user do the above and paste you the TXT value,
110
161
  then add it to their DNS.
111
162
 
112
- ## Domain options (3 paths)
113
-
114
- PRINCIPLE: domain purchase ALWAYS happens on the user's own Cloudflare account
115
- and card. Posthorn never owns or bills for domains.
116
-
117
- 1. NEW domain → requires the user's own Cloudflare account (+ payment method).
118
- - `posthorn domains check name1.com name2.io --cloudflare <id>`, fast availability + price
119
- - `posthorn domains reputation <domain>`, VET it before buying (Spamhaus
120
- blocklist/score + archive.org prior-use). Verdicts: clean / caution (used
121
- before) / avoid (blocklisted or poor reputation). Run this on the candidate
122
- before `buy`; you can't tell a tainted domain from its name. (Slower + uses
123
- a quota, so it's a separate explicit call, not part of `check`.)
124
- - `posthorn domains buy <domain> --cloudflare <id> --contact '{...}'`
125
-
126
- 2. EXISTING domain, recommended → user's own Cloudflare account.
127
- - `posthorn domains connect <domain> --cloudflare <account-id>`
128
- - (If the domain isn't on Cloudflare yet, the user adds it at dash.cloudflare.com
129
- and points nameservers to their account first.)
130
-
131
- 3. EXISTING domain, optional → Posthorn-managed DNS (no Cloudflare account needed).
132
- - `posthorn domains managed <domain>` → prints 2 nameservers
133
- - user sets them at their registrar
134
- - `posthorn domains activate <domain-id>` → checks propagation, starts DNS setup
135
- - Best for DEDICATED email-only domains. Don't use on a domain running a live
136
- website; Posthorn becomes authoritative for ALL its DNS.
137
-
138
- After any path, poll `posthorn domains get <id>` until status is `ready`. DNS
139
- records (MX, SPF, DMARC) are configured automatically. Statuses progress:
140
- pending_* → purchased → dns_configuring → dns_configured → dns_verified →
141
- workspace_verifying → workspace_verified → ready.
142
-
143
163
  ## Mailboxes & sending
144
164
 
145
165
  - Create: `posthorn mailboxes create <domain-id> --email john@dom.com --first John --last Smith`
@@ -147,19 +167,17 @@ workspace_verifying → workspace_verified → ready.
147
167
  - Credentials for IMAP/SMTP are auto-provisioned via the service account
148
168
  (domain-wide delegation). Google mailboxes need no per-mailbox setup.
149
169
  - Send: `posthorn send <mailbox-id> --to x@y.com --subject "Hi" --body "..."`
150
- (requires "verified" tier)
151
170
 
152
- ## Account verification (unlocks sending/warmup)
153
-
154
- Anonymous tier can do setup (accounts, domains). To send/warmup, verify:
155
- `posthorn auth verify` → choose admin email or a custom email → confirm the code.
171
+ There is no email-verification step anywhere: connecting your own Cloudflare
172
+ and Workspace IS the identity. Once a mailbox exists, sending and warmup work.
156
173
 
157
174
  ## Warmup
158
175
 
159
- - `posthorn warmup start <mailbox-id>` → joins the shared warmup pool, ramps over ~30 days
160
- - Volume and reply behavior are platform-managed (ramps from 2/day to 5/day;
161
- peers reply to ~30% of warmup mail). Not configurable: the pool is shared,
162
- so settings are tuned for everyone's deliverability.
176
+ - `posthorn warmup start <mailbox-id>` → joins the shared warmup pool and runs
177
+ continuously until paused
178
+ - Volume and reply behavior are platform-managed (ramps from 2/day up to
179
+ 5/day, then holds; peers reply to ~30% of warmup mail). Not configurable:
180
+ the pool is shared, so settings are tuned for everyone's deliverability.
163
181
  - `posthorn warmup stats <campaign-id>` → placement rate, reputation, daily breakdown
164
182
  - `posthorn warmup list` → all campaigns
165
183
  - Warmup never fully stops on its own, pause with `posthorn warmup pause <id>`.
@@ -169,19 +187,17 @@ Anonymous tier can do setup (accounts, domains). To send/warmup, verify:
169
187
  `posthorn feedback --type bug|feature|question|other "<message>"`
170
188
 
171
189
  If you hit a bug, missing capability, or rough edge while driving this CLI,
172
- report it, it goes straight to the Posthorn team. Agents: you are encouraged
190
+ report it; it goes straight to the Posthorn team. Agents: you are encouraged
173
191
  to file feedback yourself when something doesn't work the way you expected
174
- (include the command you ran and what you expected). Works on any tier, no
175
- verification needed.
192
+ (include the command you ran and what you expected).
193
+
194
+ Whenever you or the user get stuck, file the issue with `posthorn feedback`.
176
195
 
177
196
  ## Tips for agents
178
197
 
179
198
  - Read commands auto-detect output: when stdout isn't a TTY (i.e. you're an agent
180
199
  capturing output), they emit JSON automatically, no flag needed. Humans in a
181
200
  terminal get formatted text. Force either way with `--json` / `--pretty`.
182
- - Async steps (domain provisioning, nameserver propagation) need polling, not blocking.
183
201
  - Every command stores state locally (~/.config), so the user doesn't re-enter keys.
184
202
  - Translate everything into plain English for the user. Never show them raw JSON
185
203
  or ask them to run curl, you run the CLI on their behalf.
186
- - When a step needs the user's browser (Cloudflare token, delegation, nameservers,
187
- DKIM), give exact click-by-click instructions and wait for confirmation.
package/dist/index.js CHANGED
@@ -76,7 +76,6 @@ async function register(options) {
76
76
  spinner.succeed("Account created!");
77
77
  console.log();
78
78
  console.log(` API Key: ${chalk.cyan(data.api_key)}`);
79
- console.log(` Tier: ${chalk.yellow(data.user.tier)}`);
80
79
  console.log();
81
80
  console.log(chalk.dim(" Save this API key, it won't be shown again."));
82
81
  console.log(chalk.dim(` Config stored at: ${getConfigPath()}`));
@@ -581,7 +580,7 @@ function guide() {
581
580
 
582
581
  // src/index.ts
583
582
  var program = new Command();
584
- program.name("posthorn").description("Posthorn: domain setup, mailbox creation, and email warmup").version("0.2.6");
583
+ program.name("posthorn").description("Posthorn: domain setup, mailbox creation, and email warmup").version("0.2.8");
585
584
  program.addHelpText("after", `
586
585
  Agents: run 'posthorn guide' first for the full workflow playbook.
587
586
 
@@ -593,7 +592,6 @@ Typical flow:
593
592
  posthorn domains connect <domain> --cloudflare <id>
594
593
  posthorn domains get <id> --json poll until status: ready
595
594
  posthorn mailboxes create <domain-id> --email you@dom.com --first A --last B
596
- posthorn auth verify unlock sending + warmup
597
595
  posthorn warmup start <mailbox-id>
598
596
 
599
597
  Output: read commands auto-detect. Agents (non-TTY) get JSON, humans get
@@ -634,7 +632,9 @@ program.parseAsync(process.argv).catch((err) => {
634
632
  if (err.statusCode === 401) {
635
633
  console.log(chalk7.red("\n Authentication failed. Run: posthorn auth register\n"));
636
634
  } else if (err.statusCode === 403) {
637
- console.log(chalk7.red("\n Account not verified. Run: posthorn auth verify\n"));
635
+ console.log(chalk7.red(`
636
+ Not allowed: ${err.message}
637
+ `));
638
638
  } else if (err.statusCode === 429) {
639
639
  console.log(chalk7.yellow("\n Rate limit exceeded. Try again in a minute.\n"));
640
640
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "posthorn",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Domain setup, mailbox creation, and email warmup from the command line",
5
5
  "type": "module",
6
6
  "bin": {