@hasna/domains 0.0.22 → 0.0.24

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 CHANGED
@@ -7,11 +7,11 @@ Domain portfolio, registrar, marketplace, and DNS management for AI agents — C
7
7
  - **Domain portfolio management** — track registrar, expiry, SSL, nameservers, pricing, lifecycle status, and notes
8
8
  - **Registrar sync and purchase flows** — direct Route 53 and Namecheap registration plus GoDaddy and Brandsight provider surfaces through a shared provider registry
9
9
  - **Nameserver delegation** — Route 53 and Namecheap adapters can update registrar nameservers when the provider API supports it
10
- - **Cloudflare-first DNS** — create or reuse Cloudflare zones and manage DNS records through the DNS provider layer
10
+ - **DNS provider management** — create or reuse Cloudflare or Route 53 zones and manage DNS records through the DNS provider layer
11
11
  - **DNS record CRUD** — A, AAAA, CNAME, MX, TXT, NS, SRV records
12
12
  - **Sedo marketplace tools** — search, portfolio/listing management, blacklist checks, and recorded Sedo purchases
13
- - **AWS diagnostics** — sync Route 53 registered domains and report AWS/Beepmedia credential metadata without printing secret values
14
- - **Credential diagnostics** — redacted checks for Route 53, Beepmedia AWS env aliases, Cloudflare, Namecheap, GoDaddy, Brandsight, and Sedo
13
+ - **AWS diagnostics** — sync Route 53 registered domains and hosted zones without printing secret values
14
+ - **Credential diagnostics** — redacted checks for Route 53, Cloudflare, Namecheap, GoDaddy, Brandsight, and Sedo
15
15
  - **Expiry alerts** — set alerts for domain expiry and SSL certificate expiry
16
16
  - **WHOIS lookup** — query and store registrar/expiry info from WHOIS
17
17
  - **SSL certificate check** — verify SSL issuer and expiry
@@ -30,7 +30,7 @@ Domain portfolio, registrar, marketplace, and DNS management for AI agents — C
30
30
  npm install -g @hasna/domains
31
31
  ```
32
32
 
33
- Data is stored at `~/.hasna/domains/domains.db`. Override with `HASNA_DOMAINS_DB_PATH`, `HASNA_DOMAINS_DIR`, or `DOMAINS_DIR`.
33
+ Data is stored in the local domains data directory (`$XDG_DATA_HOME/open-domains` or `~/.local/share/open-domains` for new installs; existing legacy installs continue using their current directory). Override with `DOMAINS_DB_PATH`, `DOMAINS_DIR`, or the legacy `HASNA_DOMAINS_DB_PATH` / `HASNA_DOMAINS_DIR` names.
34
34
 
35
35
  ## Quick Start
36
36
 
@@ -38,7 +38,7 @@ Data is stored at `~/.hasna/domains/domains.db`. Override with `HASNA_DOMAINS_DB
38
38
  # Set defaults used by availability, buy, setup, DNS, and doctor commands
39
39
  domains config set default-registrar route53
40
40
  domains config set default-dns cloudflare
41
- domains config set purchase-aws-profile hasna-xyz-infra
41
+ domains config set purchase-aws-profile production-domains
42
42
 
43
43
  # Add registrant contact defaults used by registrar purchase APIs
44
44
  domains config set contact.first_name Jane
@@ -156,23 +156,23 @@ Prefer the `domains` CLI over raw registrar CLIs for Route 53 availability, regi
156
156
  ## AWS Domain Discovery
157
157
 
158
158
  ```bash
159
- # Sync registered domains from specific AWS accounts
160
- AWS_PROFILE=hasna domains sync --provider route53
161
- AWS_PROFILE=hasna-xyz-infra domains sync --provider route53
159
+ # Sync registered domains and hosted zones from specific AWS profiles
160
+ AWS_PROFILE=production-domains domains sync --provider route53
161
+ AWS_PROFILE=shared-dns domains sync --provider route53
162
162
 
163
163
  # Check all configured providers and redacted credential status
164
164
  domains providers --json
165
165
  domains doctor --json
166
166
  ```
167
167
 
168
- Route 53 sync imports registered domains when the selected AWS account permits `route53domains:ListDomains`. Beepmedia AWS metadata can be inspected through redacted diagnostics, but domain-looking SSM/Secrets names should only be imported after review because they do not prove registrar ownership.
168
+ Route 53 sync imports registered domains when the selected AWS account permits `route53domains:ListDomains`, and hosted zones when the account permits Route 53 hosted-zone reads. Domain-looking names from unrelated systems such as SSM parameters or Secrets Manager should only be imported after review because they do not prove registrar ownership.
169
169
 
170
170
  ## Storage Sync
171
171
 
172
172
  Set one of these environment variables to sync with a remote PostgreSQL storage database:
173
173
 
174
174
  ```bash
175
- export HASNA_DOMAINS_DATABASE_URL="postgres://..."
175
+ export DOMAINS_DATABASE_URL="postgres://..."
176
176
 
177
177
  domains storage status
178
178
  domains storage push
@@ -216,13 +216,16 @@ Stdio remains the default transport for gradual rollout.
216
216
 
217
217
  | Variable | Description |
218
218
  |----------|-------------|
219
+ | `DOMAINS_DB_PATH` | Override database file path |
219
220
  | `HASNA_DOMAINS_DB_PATH` | Override database file path |
221
+ | `DOMAINS_CONFIG_PATH` | Override config file path |
222
+ | `DOMAINS_CONFIG_DIR` | Override config directory |
220
223
  | `HASNA_DOMAINS_DIR` | Override database directory |
221
224
  | `DOMAINS_DIR` | Override database directory fallback |
222
- | `HASNA_DOMAINS_DATABASE_URL` | Remote storage PostgreSQL database URL |
223
- | `DOMAINS_DATABASE_URL` | Remote storage PostgreSQL database URL fallback |
224
- | `HASNA_DOMAINS_STORAGE_MODE` | Storage mode: `local`, `remote`, or `hybrid` |
225
- | `DOMAINS_STORAGE_MODE` | Storage mode fallback |
225
+ | `DOMAINS_DATABASE_URL` | Remote storage PostgreSQL database URL |
226
+ | `HASNA_DOMAINS_DATABASE_URL` | Legacy remote storage PostgreSQL database URL fallback |
227
+ | `DOMAINS_STORAGE_MODE` | Storage mode: `local`, `remote`, or `hybrid` |
228
+ | `HASNA_DOMAINS_STORAGE_MODE` | Legacy storage mode fallback |
226
229
  | `AWS_PROFILE` | AWS profile for Route 53 Domains and hosted zones |
227
230
  | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN` | AWS credential fallback |
228
231
  | `DOMAINS_PURCHASE_AWS_PROFILE` | Purchase profile fallback when config has no `purchase_aws_profile` |
@@ -236,7 +239,6 @@ Stdio remains the default transport for gradual rollout.
236
239
  | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | GoDaddy API credentials |
237
240
  | `BRANDSIGHT_API_KEY`, `BRANDSIGHT_API_SECRET`, `BRANDSIGHT_CUSTOMER_ID` | Brandsight / GoDaddy Corporate Domains credentials |
238
241
  | `SEDO_PARTNER_ID`, `SEDO_API_KEY`, `SEDO_USERNAME`, `SEDO_PASSWORD` | Sedo marketplace API credentials |
239
- | `HASNAXYZ_*` scoped aliases | Supported for Cloudflare, Brandsight, Sedo, and Beepmedia AWS diagnostics |
240
242
 
241
243
  ## License
242
244
 
@@ -1 +1 @@
1
- {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkDzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAq0B5D"}
1
+ {"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/domain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA8DzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA00B5D"}
package/dist/cli/index.js CHANGED
@@ -2348,20 +2348,26 @@ import { copyFileSync, existsSync as existsSync2, mkdirSync, readdirSync, statSy
2348
2348
  import { dirname, join as join2, resolve } from "path";
2349
2349
  import { homedir as homedir2 } from "os";
2350
2350
  function getDbPath() {
2351
+ if (process.env["DOMAINS_DB_PATH"])
2352
+ return process.env["DOMAINS_DB_PATH"];
2351
2353
  if (process.env["HASNA_DOMAINS_DB_PATH"])
2352
2354
  return process.env["HASNA_DOMAINS_DB_PATH"];
2353
- const explicit = process.env["HASNA_DOMAINS_DIR"] ?? process.env["DOMAINS_DIR"];
2355
+ const explicit = process.env["DOMAINS_DIR"] ?? process.env["HASNA_DOMAINS_DIR"];
2354
2356
  if (explicit) {
2355
2357
  return join2(explicit, "domains.db");
2356
2358
  }
2357
2359
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
2358
- migrateDotfile("domains");
2359
- return join2(home, ".hasna", "domains", "domains.db");
2360
- }
2361
- function migrateDotfile(name) {
2360
+ const legacyDir = join2(home, ".hasna", "domains");
2361
+ if (existsSync2(legacyDir))
2362
+ return join2(legacyDir, "domains.db");
2363
+ const xdgData = process.env["XDG_DATA_HOME"] || join2(home, ".local", "share");
2364
+ const newDir = join2(xdgData, "open-domains");
2365
+ migrateDotfile("domains", newDir);
2366
+ return join2(newDir, "domains.db");
2367
+ }
2368
+ function migrateDotfile(name, newDir) {
2362
2369
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir2();
2363
2370
  const oldDir = join2(home, `.${name}`);
2364
- const newDir = join2(home, ".hasna", name);
2365
2371
  if (!existsSync2(oldDir) || existsSync2(newDir))
2366
2372
  return;
2367
2373
  mkdirSync(newDir, { recursive: true });
@@ -34950,8 +34956,6 @@ function providerEnvNames(provider) {
34950
34956
  return flattenEnvNames([CLOUDFLARE_ENV.apiToken, CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email, CLOUDFLARE_ENV.accountId]);
34951
34957
  case "route53":
34952
34958
  return ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"];
34953
- case "aws:beepmedia":
34954
- return flattenEnvNames([BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
34955
34959
  default:
34956
34960
  return [];
34957
34961
  }
@@ -34973,13 +34977,11 @@ function hasProviderCredentials(provider, env = process.env) {
34973
34977
  }
34974
34978
  case "route53":
34975
34979
  return !!env["AWS_PROFILE"] || hasEveryEnv(env, [["AWS_ACCESS_KEY_ID"], ["AWS_SECRET_ACCESS_KEY"]]);
34976
- case "aws:beepmedia":
34977
- return hasEveryEnv(env, [BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
34978
34980
  default:
34979
34981
  return false;
34980
34982
  }
34981
34983
  }
34982
- var NAMECHEAP_ENV, GODADDY_ENV, BRANDSIGHT_ENV, SEDO_ENV, CLOUDFLARE_ENV, BEEPMEDIA_AWS_ENV;
34984
+ var NAMECHEAP_ENV, GODADDY_ENV, BRANDSIGHT_ENV, SEDO_ENV, CLOUDFLARE_ENV;
34983
34985
  var init_env_aliases = __esm(() => {
34984
34986
  NAMECHEAP_ENV = {
34985
34987
  apiKey: ["NAMECHEAP_API_KEY"],
@@ -34991,43 +34993,23 @@ var init_env_aliases = __esm(() => {
34991
34993
  apiSecret: ["GODADDY_API_SECRET"]
34992
34994
  };
34993
34995
  BRANDSIGHT_ENV = {
34994
- apiKey: [
34995
- "BRANDSIGHT_API_KEY",
34996
- "HASNAXYZ_BRANDSIGHT_LIVE_API_KEY",
34997
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_KEY"
34998
- ],
34999
- apiSecret: [
35000
- "BRANDSIGHT_API_SECRET",
35001
- "HASNAXYZ_BRANDSIGHT_LIVE_API_SECRET",
35002
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_SECRET"
35003
- ],
35004
- customerId: [
35005
- "BRANDSIGHT_CUSTOMER_ID",
35006
- "HASNAXYZ_BRANDSIGHT_LIVE_CUSTOMER_ID",
35007
- "HASNAXYZ_BRANDSIGHT_SANDBOX_CUSTOMER_ID"
35008
- ],
35009
- shopperId: [
35010
- "BRANDSIGHT_SHOPPER_ID",
35011
- "HASNAXYZ_BRANDSIGHT_LIVE_SHOPPER_ID",
35012
- "HASNAXYZ_BRANDSIGHT_SANDBOX_SHOPPER_ID"
35013
- ],
35014
- accountId: ["BRANDSIGHT_ACCOUNT_ID", "HASNAXYZ_BRANDSIGHT_LIVE_ACCOUNT_ID"]
34996
+ apiKey: ["BRANDSIGHT_API_KEY"],
34997
+ apiSecret: ["BRANDSIGHT_API_SECRET"],
34998
+ customerId: ["BRANDSIGHT_CUSTOMER_ID"],
34999
+ shopperId: ["BRANDSIGHT_SHOPPER_ID"],
35000
+ accountId: ["BRANDSIGHT_ACCOUNT_ID"]
35015
35001
  };
35016
35002
  SEDO_ENV = {
35017
- partnerId: ["SEDO_PARTNER_ID", "HASNAXYZ_SEDO_LIVE_PARTNER_ID"],
35018
- signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY", "HASNAXYZ_SEDO_LIVE_API_KEY"],
35019
- username: ["SEDO_USERNAME", "SEDO_EMAIL", "HASNAXYZ_SEDO_LIVE_USERNAME", "HASNAXYZ_SEDO_LIVE_EMAIL"],
35020
- password: ["SEDO_PASSWORD", "HASNAXYZ_SEDO_LIVE_PASSWORD"]
35003
+ partnerId: ["SEDO_PARTNER_ID"],
35004
+ signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY"],
35005
+ username: ["SEDO_USERNAME", "SEDO_EMAIL"],
35006
+ password: ["SEDO_PASSWORD"]
35021
35007
  };
35022
35008
  CLOUDFLARE_ENV = {
35023
- apiToken: ["CLOUDFLARE_API_TOKEN", "HASNAXYZ_CLOUDFLARE_LIVE_API_TOKEN"],
35024
- apiKey: ["CLOUDFLARE_API_KEY", "HASNAXYZ_CLOUDFLARE_LIVE_API_KEY"],
35025
- email: ["CLOUDFLARE_EMAIL", "HASNAXYZ_CLOUDFLARE_LIVE_EMAIL"],
35026
- accountId: ["CLOUDFLARE_ACCOUNT_ID", "HASNAXYZ_CLOUDFLARE_LIVE_ACCOUNT_ID"]
35027
- };
35028
- BEEPMEDIA_AWS_ENV = {
35029
- accessKeyId: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_ACCESS_KEY_ID", "BEEPMEDIA_AWS_ACCESS_KEY_ID"],
35030
- secretAccessKey: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_SECRET_ACCESS_KEY", "BEEPMEDIA_AWS_SECRET_ACCESS_KEY"]
35009
+ apiToken: ["CLOUDFLARE_API_TOKEN"],
35010
+ apiKey: ["CLOUDFLARE_API_KEY"],
35011
+ email: ["CLOUDFLARE_EMAIL"],
35012
+ accountId: ["CLOUDFLARE_ACCOUNT_ID"]
35031
35013
  };
35032
35014
  });
35033
35015
 
@@ -35302,13 +35284,13 @@ function brandsightCapability(env = process.env) {
35302
35284
  return {
35303
35285
  configured,
35304
35286
  gated: true,
35305
- notes: configured ? "Credentials present, but GoDaddy Corporate Domains (Brandsight) is enterprise/contract-only; use Route53 for automated purchase." : "Not configured and enterprise/contract-only; not usable for automated purchase."
35287
+ notes: configured ? "Credentials present, but GoDaddy Corporate Domains (Brandsight) registration and renewal are enterprise/contract-gated." : "Not configured; GoDaddy Corporate Domains (Brandsight) is enterprise/contract-gated."
35306
35288
  };
35307
35289
  }
35308
35290
  function getApiKey() {
35309
35291
  const key = resolveBrandsightConfig().apiKey;
35310
35292
  if (!key) {
35311
- throw new BrandsightApiError("Brandsight API key is not set. Set BRANDSIGHT_API_KEY or HASNAXYZ_BRANDSIGHT_LIVE_API_KEY.");
35293
+ throw new BrandsightApiError("Brandsight API key is not set. Set BRANDSIGHT_API_KEY.");
35312
35294
  }
35313
35295
  return key;
35314
35296
  }
@@ -35344,7 +35326,7 @@ async function apiGet(path, apiKey, baseUrl = BRANDSIGHT_BASE) {
35344
35326
  function requireDomainConfig(config) {
35345
35327
  const cfg = config ?? getConfig4();
35346
35328
  if (!cfg.apiKey || !cfg.apiSecret || !cfg.customerId) {
35347
- throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID (or HASNAXYZ_BRANDSIGHT_LIVE_* aliases).");
35329
+ throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID.");
35348
35330
  }
35349
35331
  return cfg;
35350
35332
  }
@@ -35791,9 +35773,9 @@ __export(exports_config, {
35791
35773
  });
35792
35774
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
35793
35775
  import { homedir as homedir4 } from "os";
35794
- import { join as join4 } from "path";
35776
+ import { dirname as dirname4, join as join4 } from "path";
35795
35777
  function getPurchaseProfile() {
35796
- return loadConfig3().purchase_aws_profile ?? process.env["DOMAINS_PURCHASE_AWS_PROFILE"] ?? undefined;
35778
+ return process.env["DOMAINS_PURCHASE_AWS_PROFILE"] ?? loadConfig3().purchase_aws_profile ?? undefined;
35797
35779
  }
35798
35780
  function applyPurchaseProfile() {
35799
35781
  if (process.env["AWS_ACCESS_KEY_ID"] || process.env["AWS_PROFILE"])
@@ -35804,7 +35786,16 @@ function applyPurchaseProfile() {
35804
35786
  return profile;
35805
35787
  }
35806
35788
  function configPath() {
35807
- return join4(homedir4(), ".hasna", "domains", "config.json");
35789
+ if (process.env["DOMAINS_CONFIG_PATH"])
35790
+ return process.env["DOMAINS_CONFIG_PATH"];
35791
+ const dir = process.env["DOMAINS_CONFIG_DIR"];
35792
+ if (dir)
35793
+ return join4(dir, "config.json");
35794
+ const legacyDir = join4(homedir4(), ".hasna", "domains");
35795
+ if (existsSync3(legacyDir))
35796
+ return join4(legacyDir, "config.json");
35797
+ const xdgConfig = process.env["XDG_CONFIG_HOME"] || join4(homedir4(), ".config");
35798
+ return join4(xdgConfig, "open-domains", "config.json");
35808
35799
  }
35809
35800
  function loadConfig3() {
35810
35801
  const path = configPath();
@@ -35818,7 +35809,7 @@ function loadConfig3() {
35818
35809
  }
35819
35810
  function saveConfig(config) {
35820
35811
  const path = configPath();
35821
- const dir = join4(homedir4(), ".hasna", "domains");
35812
+ const dir = dirname4(path);
35822
35813
  if (!existsSync3(dir))
35823
35814
  mkdirSync2(dir, { recursive: true });
35824
35815
  writeFileSync(path, JSON.stringify(config, null, 2), "utf-8");
@@ -35977,7 +35968,7 @@ function getSedoConfig() {
35977
35968
  const config = resolveSedoConfig();
35978
35969
  const { partnerId, signKey, username, password } = config;
35979
35970
  if (!partnerId || !signKey || !username || !password) {
35980
- throw new Error("Sedo credentials not configured. Required: SEDO_PARTNER_ID, SEDO_API_KEY, SEDO_USERNAME, SEDO_PASSWORD (or HASNAXYZ_SEDO_LIVE_* aliases)");
35971
+ throw new Error("Sedo credentials not configured. Required: SEDO_PARTNER_ID, SEDO_API_KEY, SEDO_USERNAME, SEDO_PASSWORD");
35981
35972
  }
35982
35973
  return { partnerId, signKey, username, password };
35983
35974
  }
@@ -36213,13 +36204,6 @@ function checkProvisioningCredentials(env = process.env) {
36213
36204
  } else {
36214
36205
  out.push(missingStatus("route53", "Set AWS_PROFILE or AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY"));
36215
36206
  }
36216
- const beepmediaAws = hasProviderCredentials("aws:beepmedia", env);
36217
- out.push({
36218
- provider: "aws:beepmedia",
36219
- configured: beepmediaAws,
36220
- mode: beepmediaAws ? "scoped-env" : "none",
36221
- detail: beepmediaAws ? "Beepmedia AWS scoped env keys are present; export them as AWS_* or use AWS_PROFILE=beepmedia for Route53 sync." : `Set ${BEEPMEDIA_AWS_ENV.accessKeyId.join(" or ")} and ${BEEPMEDIA_AWS_ENV.secretAccessKey.join(" or ")}`
36222
- });
36223
36207
  const cf = resolveCloudflareConfig(env);
36224
36208
  const cfMode = cf.apiToken ? "token" : cf.apiKey && cf.email ? "global-key" : "none";
36225
36209
  out.push({
@@ -36242,7 +36226,7 @@ function checkProvisioningCredentials(env = process.env) {
36242
36226
  detail: gd.notes
36243
36227
  });
36244
36228
  const bs = brandsightCapability(env);
36245
- const bsMode = firstEnv(env, ["BRANDSIGHT_API_KEY"]) ? "standard-env" : bs.configured ? "scoped-env" : "none";
36229
+ const bsMode = firstEnv(env, ["BRANDSIGHT_API_KEY"]) ? "standard-env" : "none";
36246
36230
  out.push({
36247
36231
  provider: "brandsight",
36248
36232
  configured: bs.configured,
@@ -36250,7 +36234,7 @@ function checkProvisioningCredentials(env = process.env) {
36250
36234
  detail: bs.notes
36251
36235
  });
36252
36236
  const sedo = sedoCapability(env);
36253
- const sedoMode = firstEnv(env, ["SEDO_API_KEY"]) ? "standard-env" : sedo.configured ? "scoped-env" : "none";
36237
+ const sedoMode = firstEnv(env, ["SEDO_API_KEY"]) ? "standard-env" : "none";
36254
36238
  out.push({
36255
36239
  provider: "sedo",
36256
36240
  configured: sedo.configured,
@@ -42619,6 +42603,17 @@ function parseOptionalNumber(value, flagName) {
42619
42603
  }
42620
42604
  return parsed;
42621
42605
  }
42606
+ async function createDnsZoneForProvider(domain, provider) {
42607
+ if (provider === "cloudflare") {
42608
+ const zone = await ensureZone(domain);
42609
+ return { zoneId: zone.id, nameservers: zone.nameservers ?? [] };
42610
+ }
42611
+ if (provider === "route53") {
42612
+ const zone = await createHostedZone(domain, "Managed by domains CLI");
42613
+ return { zoneId: zone.id, nameservers: zone.name_servers ?? [] };
42614
+ }
42615
+ throw new Error(`DNS provider '${provider}' is not supported by domain purchase delegation yet`);
42616
+ }
42622
42617
  function requireDomain(identifier) {
42623
42618
  const details = getDomainDetails(identifier);
42624
42619
  if (!details) {
@@ -43029,7 +43024,7 @@ WHOIS for ${result.domain} [${result.source}]:`);
43029
43024
  process.exit(1);
43030
43025
  }
43031
43026
  });
43032
- domain.command("buy <name>").description("Purchase or record a domain via registrar provider (contact defaults from: domains config set contact.*)").option("--provider <name>", "Registrar provider (default: config default-registrar or route53)").option("--registrar <name>", "Registrar/seller for recorded purchases (alias of --provider)").option("--email <email>", "Registrant email").option("--first-name <n>", "First name").option("--last-name <n>", "Last name").option("--phone <p>", "Phone").option("--address <a>", "Street address").option("--city <c>", "City").option("--state <s>", "State/province").option("--country <c>", "Country code").option("--zip <z>", "ZIP code").option("--org <o>", "Organization").option("--price <amount>", "Record a completed purchase instead of registering via Route 53").option("--expires <date>", "Expiry date for recorded purchases").option("--auto-renew <bool>", "Auto-renew for recorded purchases (true/false)").option("--years <n>", "Years", "1").option("--wait", "Poll until registration completes").option("--dns <provider>", "DNS provider to delegate to after purchase (always cloudflare)", "cloudflare").option("--no-delegate", "Skip delegating DNS to Cloudflare after purchase").action(async (name, opts) => {
43027
+ domain.command("buy <name>").description("Purchase or record a domain via registrar provider (contact defaults from: domains config set contact.*)").option("--provider <name>", "Registrar provider (default: config default-registrar or route53)").option("--registrar <name>", "Registrar/seller for recorded purchases (alias of --provider)").option("--email <email>", "Registrant email").option("--first-name <n>", "First name").option("--last-name <n>", "Last name").option("--phone <p>", "Phone").option("--address <a>", "Street address").option("--city <c>", "City").option("--state <s>", "State/province").option("--country <c>", "Country code").option("--zip <z>", "ZIP code").option("--org <o>", "Organization").option("--price <amount>", "Record a completed purchase instead of registering via Route 53").option("--expires <date>", "Expiry date for recorded purchases").option("--auto-renew <bool>", "Auto-renew for recorded purchases (true/false)").option("--years <n>", "Years", "1").option("--wait", "Poll until registration completes").option("--dns <provider>", "DNS provider to delegate to after purchase (default: config default-dns or cloudflare)").option("--no-delegate", "Skip nameserver delegation after purchase").action(async (name, opts) => {
43033
43028
  const recordedPrice = parseOptionalNumber(opts.price, "--price");
43034
43029
  if (recordedPrice !== undefined) {
43035
43030
  const registrarName = opts.registrar ?? opts.provider ?? "manual";
@@ -43053,6 +43048,7 @@ WHOIS for ${result.domain} [${result.source}]:`);
43053
43048
  }
43054
43049
  const cfg = loadConfig3();
43055
43050
  const providerName = opts.registrar ?? opts.provider ?? cfg.default_registrar ?? "route53";
43051
+ const dnsProvider = opts.dns ?? cfg.default_dns ?? "cloudflare";
43056
43052
  const purchaseProfile = providerName === "route53" ? applyPurchaseProfile() : undefined;
43057
43053
  if (purchaseProfile)
43058
43054
  console.log(`Using purchase AWS profile: ${purchaseProfile}`);
@@ -43104,17 +43100,16 @@ WHOIS for ${result.domain} [${result.source}]:`);
43104
43100
  console.log(`\u2713 Registered and added to portfolio`);
43105
43101
  if (reg.orderId)
43106
43102
  console.log(` Order: ${reg.orderId}`);
43107
- const dnsProvider = opts.dns ?? "cloudflare";
43108
- if (opts.delegate !== false && dnsProvider === "cloudflare") {
43103
+ if (opts.delegate !== false) {
43109
43104
  if (!provider.updateNameservers) {
43110
43105
  console.log(` DNS: ${providerName} registration succeeded, but nameserver updates are not implemented for this provider.`);
43111
43106
  } else {
43112
- const zone = await ensureZone(name);
43107
+ const zone = await createDnsZoneForProvider(name, dnsProvider);
43113
43108
  const nsUpdate = await provider.updateNameservers(name, zone.nameservers);
43114
43109
  const existing2 = getDomainByName(name);
43115
43110
  if (existing2)
43116
43111
  updateDomain(existing2.id, { nameservers: zone.nameservers });
43117
- console.log(`\u2713 Cloudflare zone ${zone.id}; nameservers updated${nsUpdate.operationId ? ` (op ${nsUpdate.operationId})` : ""}`);
43112
+ console.log(`\u2713 ${dnsProvider} zone ${zone.zoneId}; nameservers updated${nsUpdate.operationId ? ` (op ${nsUpdate.operationId})` : ""}`);
43118
43113
  }
43119
43114
  }
43120
43115
  return;
@@ -43178,27 +43173,30 @@ WHOIS for ${result.domain} [${result.source}]:`);
43178
43173
  });
43179
43174
  }
43180
43175
  console.log(`\u2713 Added to portfolio`);
43181
- const dnsProvider = opts.dns ?? "cloudflare";
43182
- if (opts.delegate !== false && dnsProvider === "cloudflare") {
43176
+ if (opts.delegate !== false) {
43183
43177
  if (!opts.wait) {
43184
43178
  console.log(` DNS: run 'domains domain buy ${name} --wait' or delegate later \u2014 registration must finish before NS can change.`);
43185
43179
  } else {
43186
43180
  try {
43187
- console.log(`Delegating DNS to Cloudflare...`);
43188
- const del = await delegateDomainToCloudflare(name, {
43181
+ console.log(`Delegating DNS to ${dnsProvider}...`);
43182
+ const del = dnsProvider === "cloudflare" ? await delegateDomainToCloudflare(name, {
43189
43183
  createCloudflareZone: async (d3) => {
43190
43184
  const z2 = await ensureZone(d3);
43191
43185
  return { id: z2.id, nameservers: z2.nameservers };
43192
43186
  },
43193
43187
  updateNameservers: (d3, ns) => updateNameservers2(d3, ns)
43194
- });
43188
+ }) : await (async () => {
43189
+ const zone = await createDnsZoneForProvider(name, dnsProvider);
43190
+ const nsUpdate = await updateNameservers2(name, zone.nameservers);
43191
+ return { zoneId: zone.zoneId, nameservers: zone.nameservers, operationId: nsUpdate.operationId };
43192
+ })();
43195
43193
  const existing2 = getDomainByName(name);
43196
43194
  if (existing2)
43197
43195
  updateDomain(existing2.id, { nameservers: del.nameservers });
43198
- console.log(`\u2713 Cloudflare zone ${del.zoneId}; nameservers \u2192 ${del.nameservers.join(", ")} (op ${del.operationId})`);
43196
+ console.log(`\u2713 ${dnsProvider} zone ${del.zoneId}; nameservers \u2192 ${del.nameservers.join(", ")} (op ${del.operationId})`);
43199
43197
  } catch (e3) {
43200
43198
  console.error(`\u26A0 DNS delegation failed (domain is registered): ${e3 instanceof Error ? e3.message : String(e3)}`);
43201
- console.error(` Retry: create the Cloudflare zone and point Route53 NS at it.`);
43199
+ console.error(` Retry: create the DNS zone and point Route53 NS at it.`);
43202
43200
  }
43203
43201
  }
43204
43202
  }
@@ -43263,7 +43261,7 @@ Setting up ${name}`);
43263
43261
  nameservers = zone.nameservers ?? [];
43264
43262
  console.log("ready (" + zone.id + ")");
43265
43263
  } else {
43266
- const zone = await createHostedZone(name, `Managed by @hasna/domains`);
43264
+ const zone = await createHostedZone(name, "Managed by domains CLI");
43267
43265
  nameservers = zone.name_servers ?? [];
43268
43266
  console.log(`created (${zone.id})`);
43269
43267
  }
@@ -44120,7 +44118,7 @@ function registerConfigCommands(program2) {
44120
44118
  return;
44121
44119
  }
44122
44120
  console.log(`
44123
- Configuration (~/.hasna/domains/config.json):`);
44121
+ Configuration:`);
44124
44122
  console.log(` default-registrar: ${cfg.default_registrar ?? "(not set)"}`);
44125
44123
  console.log(` default-dns: ${cfg.default_dns ?? "(not set)"}`);
44126
44124
  console.log(` purchase-aws-profile: ${cfg.purchase_aws_profile ?? "(not set)"}`);
@@ -44197,7 +44195,7 @@ function registerDoctorCommand(program2) {
44197
44195
  const count = countDomains();
44198
44196
  ok(`Local DB accessible (${count} domain${count !== 1 ? "s" : ""})`);
44199
44197
  } catch {
44200
- fail("Local DB not accessible", "Check ~/.hasna/domains/domains.db");
44198
+ fail("Local DB not accessible", "Check DOMAINS_DB_PATH, DOMAINS_DIR, or the default local data directory");
44201
44199
  }
44202
44200
  section("Config");
44203
44201
  const cfg = loadConfig3();
@@ -44276,7 +44274,7 @@ ${"\u2500".repeat(45)}`);
44276
44274
  // src/cli/commands/mcp-install.ts
44277
44275
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
44278
44276
  import { homedir as homedir5 } from "os";
44279
- import { dirname as dirname4, join as join5 } from "path";
44277
+ import { dirname as dirname5, join as join5 } from "path";
44280
44278
  import { execSync as execSync3 } from "child_process";
44281
44279
  var MCP_SERVER_NAME = "domains";
44282
44280
  function getClaudeConfigPaths() {
@@ -44293,7 +44291,7 @@ function getMcpBinaryPath() {
44293
44291
  }
44294
44292
  }
44295
44293
  function ensureConfigDir(configPath2) {
44296
- const dir = dirname4(configPath2);
44294
+ const dir = dirname5(configPath2);
44297
44295
  if (!existsSync4(dir)) {
44298
44296
  mkdirSync3(dir, { recursive: true });
44299
44297
  }
@@ -44893,7 +44891,7 @@ DNS Records for ${domain}:`);
44893
44891
  return { id: full.id, name_servers: full.name_servers };
44894
44892
  },
44895
44893
  createZone: async (d3) => {
44896
- const z2 = await createHostedZone(d3, `Managed by @hasna/domains`);
44894
+ const z2 = await createHostedZone(d3, "Managed by domains CLI");
44897
44895
  return { id: z2.id, name_servers: z2.name_servers ?? [] };
44898
44896
  },
44899
44897
  getRegistrarNs: async (d3) => (await getDomainDetail(d3)).nameservers,
@@ -47276,10 +47274,10 @@ var PRIMARY_KEYS = {
47276
47274
  domain_history: ["id"],
47277
47275
  domain_reputation: ["id"]
47278
47276
  };
47279
- var DOMAINS_STORAGE_ENV = "HASNA_DOMAINS_DATABASE_URL";
47280
- var DOMAINS_STORAGE_FALLBACK_ENV = "DOMAINS_DATABASE_URL";
47281
- var DOMAINS_STORAGE_MODE_ENV = "HASNA_DOMAINS_STORAGE_MODE";
47282
- var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "DOMAINS_STORAGE_MODE";
47277
+ var DOMAINS_STORAGE_ENV = "DOMAINS_DATABASE_URL";
47278
+ var DOMAINS_STORAGE_FALLBACK_ENV = "HASNA_DOMAINS_DATABASE_URL";
47279
+ var DOMAINS_STORAGE_MODE_ENV = "DOMAINS_STORAGE_MODE";
47280
+ var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "HASNA_DOMAINS_STORAGE_MODE";
47283
47281
  var STORAGE_DATABASE_ENV = [DOMAINS_STORAGE_ENV, DOMAINS_STORAGE_FALLBACK_ENV];
47284
47282
  var STORAGE_MODE_ENV = [DOMAINS_STORAGE_MODE_ENV, DOMAINS_STORAGE_MODE_FALLBACK_ENV];
47285
47283
  function firstEnv2(names) {
@@ -47307,7 +47305,7 @@ function getStorageMode() {
47307
47305
  async function getStoragePg() {
47308
47306
  const url = getStorageDatabaseUrl();
47309
47307
  if (!url) {
47310
- throw new Error("Missing HASNA_DOMAINS_DATABASE_URL or DOMAINS_DATABASE_URL");
47308
+ throw new Error("Missing DOMAINS_DATABASE_URL or HASNA_DOMAINS_DATABASE_URL");
47311
47309
  }
47312
47310
  return new PgAdapterAsync(url);
47313
47311
  }
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAiCtC,wBAAgB,WAAW,IAAI,QAAQ,CA8CtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAsCtC,wBAAgB,WAAW,IAAI,QAAQ,CA8CtC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
@@ -24,12 +24,12 @@ export interface StorageStatus {
24
24
  tables: typeof STORAGE_TABLES;
25
25
  sync: StorageSyncMeta[];
26
26
  }
27
- export declare const DOMAINS_STORAGE_ENV = "HASNA_DOMAINS_DATABASE_URL";
28
- export declare const DOMAINS_STORAGE_FALLBACK_ENV = "DOMAINS_DATABASE_URL";
29
- export declare const DOMAINS_STORAGE_MODE_ENV = "HASNA_DOMAINS_STORAGE_MODE";
30
- export declare const DOMAINS_STORAGE_MODE_FALLBACK_ENV = "DOMAINS_STORAGE_MODE";
31
- export declare const STORAGE_DATABASE_ENV: readonly ["HASNA_DOMAINS_DATABASE_URL", "DOMAINS_DATABASE_URL"];
32
- export declare const STORAGE_MODE_ENV: readonly ["HASNA_DOMAINS_STORAGE_MODE", "DOMAINS_STORAGE_MODE"];
27
+ export declare const DOMAINS_STORAGE_ENV = "DOMAINS_DATABASE_URL";
28
+ export declare const DOMAINS_STORAGE_FALLBACK_ENV = "HASNA_DOMAINS_DATABASE_URL";
29
+ export declare const DOMAINS_STORAGE_MODE_ENV = "DOMAINS_STORAGE_MODE";
30
+ export declare const DOMAINS_STORAGE_MODE_FALLBACK_ENV = "HASNA_DOMAINS_STORAGE_MODE";
31
+ export declare const STORAGE_DATABASE_ENV: readonly ["DOMAINS_DATABASE_URL", "HASNA_DOMAINS_DATABASE_URL"];
32
+ export declare const STORAGE_MODE_ENV: readonly ["DOMAINS_STORAGE_MODE", "HASNA_DOMAINS_STORAGE_MODE"];
33
33
  export declare function getStorageDatabaseUrl(): string | null;
34
34
  export declare function getStorageDatabaseEnvName(): (typeof STORAGE_DATABASE_ENV)[number] | null;
35
35
  export declare function getStorageMode(): StorageMode;
@@ -1 +1 @@
1
- {"version":3,"file":"storage-sync.d.ts","sourceRoot":"","sources":["../../src/db/storage-sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,eAAO,MAAM,cAAc,yIASjB,CAAC;AACX,eAAO,MAAM,sBAAsB,yIAAiB,CAAC;AAErD,KAAK,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAcpD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAC3C,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC;AAEvC,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,OAAO,oBAAoB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,SAAS,CAAC;IACnB,MAAM,EAAE,OAAO,cAAc,CAAC;IAC9B,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAChE,eAAO,MAAM,4BAA4B,yBAAyB,CAAC;AACnE,eAAO,MAAM,wBAAwB,+BAA+B,CAAC;AACrE,eAAO,MAAM,iCAAiC,yBAAyB,CAAC;AACxE,eAAO,MAAM,oBAAoB,iEAA+D,CAAC;AACjG,eAAO,MAAM,gBAAgB,iEAAyE,CAAC;AAiBvG,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,yBAAyB,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAKxF;AAED,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAM5D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhF;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAY/F;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAY/F;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAAC,IAAI,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CAIpI;AAED,wBAAgB,qBAAqB,IAAI,eAAe,EAAE,CAIzD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAShD;AAED,wBAAgB,cAAc,IAAI,eAAe,EAAE,CAElD;AAED,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAO/D"}
1
+ {"version":3,"file":"storage-sync.d.ts","sourceRoot":"","sources":["../../src/db/storage-sync.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,eAAO,MAAM,cAAc,yIASjB,CAAC;AACX,eAAO,MAAM,sBAAsB,yIAAiB,CAAC;AAErD,KAAK,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAcpD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAExD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAC3C,MAAM,MAAM,QAAQ,GAAG,eAAe,CAAC;AAEvC,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,GAAG,EAAE,OAAO,oBAAoB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,SAAS,CAAC;IACnB,MAAM,EAAE,OAAO,cAAc,CAAC;IAC9B,IAAI,EAAE,eAAe,EAAE,CAAC;CACzB;AAED,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAC1D,eAAO,MAAM,4BAA4B,+BAA+B,CAAC;AACzE,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAC/D,eAAO,MAAM,iCAAiC,+BAA+B,CAAC;AAC9E,eAAO,MAAM,oBAAoB,iEAA+D,CAAC;AACjG,eAAO,MAAM,gBAAgB,iEAAyE,CAAC;AAiBvG,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAErD;AAED,wBAAgB,yBAAyB,IAAI,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAKxF;AAED,wBAAgB,cAAc,IAAI,WAAW,CAG5C;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,cAAc,CAAC,CAM5D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhF;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAY/F;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAY/F;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;IAAC,IAAI,EAAE,iBAAiB,EAAE,CAAA;CAAE,CAAC,CAIpI;AAED,wBAAgB,qBAAqB,IAAI,eAAe,EAAE,CAIzD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,CAShD;AAED,wBAAgB,cAAc,IAAI,eAAe,EAAE,CAElD;AAED,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAO/D"}
package/dist/index.js CHANGED
@@ -27352,20 +27352,26 @@ var MIGRATIONS = [
27352
27352
  // src/db/database.ts
27353
27353
  var _db = null;
27354
27354
  function getDbPath() {
27355
+ if (process.env["DOMAINS_DB_PATH"])
27356
+ return process.env["DOMAINS_DB_PATH"];
27355
27357
  if (process.env["HASNA_DOMAINS_DB_PATH"])
27356
27358
  return process.env["HASNA_DOMAINS_DB_PATH"];
27357
- const explicit = process.env["HASNA_DOMAINS_DIR"] ?? process.env["DOMAINS_DIR"];
27359
+ const explicit = process.env["DOMAINS_DIR"] ?? process.env["HASNA_DOMAINS_DIR"];
27358
27360
  if (explicit) {
27359
27361
  return join(explicit, "domains.db");
27360
27362
  }
27361
27363
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
27362
- migrateDotfile("domains");
27363
- return join(home, ".hasna", "domains", "domains.db");
27364
- }
27365
- function migrateDotfile(name) {
27364
+ const legacyDir = join(home, ".hasna", "domains");
27365
+ if (existsSync(legacyDir))
27366
+ return join(legacyDir, "domains.db");
27367
+ const xdgData = process.env["XDG_DATA_HOME"] || join(home, ".local", "share");
27368
+ const newDir = join(xdgData, "open-domains");
27369
+ migrateDotfile("domains", newDir);
27370
+ return join(newDir, "domains.db");
27371
+ }
27372
+ function migrateDotfile(name, newDir) {
27366
27373
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
27367
27374
  const oldDir = join(home, `.${name}`);
27368
- const newDir = join(home, ".hasna", name);
27369
27375
  if (!existsSync(oldDir) || existsSync(newDir))
27370
27376
  return;
27371
27377
  mkdirSync(newDir, { recursive: true });
@@ -28655,10 +28661,10 @@ var PRIMARY_KEYS = {
28655
28661
  domain_history: ["id"],
28656
28662
  domain_reputation: ["id"]
28657
28663
  };
28658
- var DOMAINS_STORAGE_ENV = "HASNA_DOMAINS_DATABASE_URL";
28659
- var DOMAINS_STORAGE_FALLBACK_ENV = "DOMAINS_DATABASE_URL";
28660
- var DOMAINS_STORAGE_MODE_ENV = "HASNA_DOMAINS_STORAGE_MODE";
28661
- var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "DOMAINS_STORAGE_MODE";
28664
+ var DOMAINS_STORAGE_ENV = "DOMAINS_DATABASE_URL";
28665
+ var DOMAINS_STORAGE_FALLBACK_ENV = "HASNA_DOMAINS_DATABASE_URL";
28666
+ var DOMAINS_STORAGE_MODE_ENV = "DOMAINS_STORAGE_MODE";
28667
+ var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "HASNA_DOMAINS_STORAGE_MODE";
28662
28668
  var STORAGE_DATABASE_ENV = [DOMAINS_STORAGE_ENV, DOMAINS_STORAGE_FALLBACK_ENV];
28663
28669
  var STORAGE_MODE_ENV = [DOMAINS_STORAGE_MODE_ENV, DOMAINS_STORAGE_MODE_FALLBACK_ENV];
28664
28670
  function firstEnv(names) {
@@ -28693,7 +28699,7 @@ function getStorageMode() {
28693
28699
  async function getStoragePg() {
28694
28700
  const url = getStorageDatabaseUrl();
28695
28701
  if (!url) {
28696
- throw new Error("Missing HASNA_DOMAINS_DATABASE_URL or DOMAINS_DATABASE_URL");
28702
+ throw new Error("Missing DOMAINS_DATABASE_URL or HASNA_DOMAINS_DATABASE_URL");
28697
28703
  }
28698
28704
  return new PgAdapterAsync(url);
28699
28705
  }
@@ -36204,43 +36210,23 @@ var GODADDY_ENV = {
36204
36210
  apiSecret: ["GODADDY_API_SECRET"]
36205
36211
  };
36206
36212
  var BRANDSIGHT_ENV = {
36207
- apiKey: [
36208
- "BRANDSIGHT_API_KEY",
36209
- "HASNAXYZ_BRANDSIGHT_LIVE_API_KEY",
36210
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_KEY"
36211
- ],
36212
- apiSecret: [
36213
- "BRANDSIGHT_API_SECRET",
36214
- "HASNAXYZ_BRANDSIGHT_LIVE_API_SECRET",
36215
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_SECRET"
36216
- ],
36217
- customerId: [
36218
- "BRANDSIGHT_CUSTOMER_ID",
36219
- "HASNAXYZ_BRANDSIGHT_LIVE_CUSTOMER_ID",
36220
- "HASNAXYZ_BRANDSIGHT_SANDBOX_CUSTOMER_ID"
36221
- ],
36222
- shopperId: [
36223
- "BRANDSIGHT_SHOPPER_ID",
36224
- "HASNAXYZ_BRANDSIGHT_LIVE_SHOPPER_ID",
36225
- "HASNAXYZ_BRANDSIGHT_SANDBOX_SHOPPER_ID"
36226
- ],
36227
- accountId: ["BRANDSIGHT_ACCOUNT_ID", "HASNAXYZ_BRANDSIGHT_LIVE_ACCOUNT_ID"]
36213
+ apiKey: ["BRANDSIGHT_API_KEY"],
36214
+ apiSecret: ["BRANDSIGHT_API_SECRET"],
36215
+ customerId: ["BRANDSIGHT_CUSTOMER_ID"],
36216
+ shopperId: ["BRANDSIGHT_SHOPPER_ID"],
36217
+ accountId: ["BRANDSIGHT_ACCOUNT_ID"]
36228
36218
  };
36229
36219
  var SEDO_ENV = {
36230
- partnerId: ["SEDO_PARTNER_ID", "HASNAXYZ_SEDO_LIVE_PARTNER_ID"],
36231
- signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY", "HASNAXYZ_SEDO_LIVE_API_KEY"],
36232
- username: ["SEDO_USERNAME", "SEDO_EMAIL", "HASNAXYZ_SEDO_LIVE_USERNAME", "HASNAXYZ_SEDO_LIVE_EMAIL"],
36233
- password: ["SEDO_PASSWORD", "HASNAXYZ_SEDO_LIVE_PASSWORD"]
36220
+ partnerId: ["SEDO_PARTNER_ID"],
36221
+ signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY"],
36222
+ username: ["SEDO_USERNAME", "SEDO_EMAIL"],
36223
+ password: ["SEDO_PASSWORD"]
36234
36224
  };
36235
36225
  var CLOUDFLARE_ENV = {
36236
- apiToken: ["CLOUDFLARE_API_TOKEN", "HASNAXYZ_CLOUDFLARE_LIVE_API_TOKEN"],
36237
- apiKey: ["CLOUDFLARE_API_KEY", "HASNAXYZ_CLOUDFLARE_LIVE_API_KEY"],
36238
- email: ["CLOUDFLARE_EMAIL", "HASNAXYZ_CLOUDFLARE_LIVE_EMAIL"],
36239
- accountId: ["CLOUDFLARE_ACCOUNT_ID", "HASNAXYZ_CLOUDFLARE_LIVE_ACCOUNT_ID"]
36240
- };
36241
- var BEEPMEDIA_AWS_ENV = {
36242
- accessKeyId: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_ACCESS_KEY_ID", "BEEPMEDIA_AWS_ACCESS_KEY_ID"],
36243
- secretAccessKey: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_SECRET_ACCESS_KEY", "BEEPMEDIA_AWS_SECRET_ACCESS_KEY"]
36226
+ apiToken: ["CLOUDFLARE_API_TOKEN"],
36227
+ apiKey: ["CLOUDFLARE_API_KEY"],
36228
+ email: ["CLOUDFLARE_EMAIL"],
36229
+ accountId: ["CLOUDFLARE_ACCOUNT_ID"]
36244
36230
  };
36245
36231
  function providerEnvNames(provider) {
36246
36232
  switch (provider.toLowerCase()) {
@@ -36262,8 +36248,6 @@ function providerEnvNames(provider) {
36262
36248
  return flattenEnvNames([CLOUDFLARE_ENV.apiToken, CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email, CLOUDFLARE_ENV.accountId]);
36263
36249
  case "route53":
36264
36250
  return ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"];
36265
- case "aws:beepmedia":
36266
- return flattenEnvNames([BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
36267
36251
  default:
36268
36252
  return [];
36269
36253
  }
@@ -36285,8 +36269,6 @@ function hasProviderCredentials(provider, env = process.env) {
36285
36269
  }
36286
36270
  case "route53":
36287
36271
  return !!env["AWS_PROFILE"] || hasEveryEnv(env, [["AWS_ACCESS_KEY_ID"], ["AWS_SECRET_ACCESS_KEY"]]);
36288
- case "aws:beepmedia":
36289
- return hasEveryEnv(env, [BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
36290
36272
  default:
36291
36273
  return false;
36292
36274
  }
@@ -36583,7 +36565,7 @@ var BRANDSIGHT_DOMAIN_BASE = "https://api.godaddy.com/v2";
36583
36565
  function requireDomainConfig(config) {
36584
36566
  const cfg = config ?? getConfig4();
36585
36567
  if (!cfg.apiKey || !cfg.apiSecret || !cfg.customerId) {
36586
- throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID (or HASNAXYZ_BRANDSIGHT_LIVE_* aliases).");
36568
+ throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID.");
36587
36569
  }
36588
36570
  return cfg;
36589
36571
  }
@@ -37284,7 +37266,7 @@ async function delegateDomainToCloudflare(domain, deps) {
37284
37266
  // src/lib/capability.ts
37285
37267
  var PROVIDER_CAPABILITIES = {
37286
37268
  route53: { canBuy: true, canDns: true, gated: false, notes: "Full self-serve buy + hosted zones via AWS API; primary buy path." },
37287
- cloudflare: { canBuy: false, canDns: true, gated: false, notes: "DNS/zone management only; not a registrar. Always our DNS." },
37269
+ cloudflare: { canBuy: false, canDns: true, gated: false, notes: "DNS/zone management only; not a registrar." },
37288
37270
  namecheap: { canBuy: true, canDns: true, gated: false, notes: "Buy + DNS via API; requires API access + whitelisted IP." },
37289
37271
  godaddy: { canBuy: false, canDns: true, gated: true, notes: "Availability remains threshold-gated; this CLI supports sync/renew/DNS records where account access qualifies, but not direct automated purchase." },
37290
37272
  brandsight: { canBuy: true, canDns: true, gated: true, notes: "GoDaddy Corporate Domains (enterprise/contract-only); this CLI supports portfolio, registration, renewal, nameserver, and DNS operations through the official v2 API when the account contract permits it." },
@@ -37309,7 +37291,15 @@ function selectBuyRegistrar(preference) {
37309
37291
  }
37310
37292
  return "route53";
37311
37293
  }
37312
- function selectDnsProvider() {
37294
+ function selectDnsProvider(preference) {
37295
+ if (preference) {
37296
+ const c3 = getCapability(preference);
37297
+ if (!c3.canDns)
37298
+ throw new Error(`Provider '${preference}' cannot manage DNS`);
37299
+ if (c3.gated)
37300
+ throw new Error(`Provider '${preference}' DNS is gated and may require account approval: ${c3.notes}`);
37301
+ return preference.toLowerCase();
37302
+ }
37313
37303
  return "cloudflare";
37314
37304
  }
37315
37305
  // src/lib/registration-poll.ts
@@ -9,7 +9,7 @@
9
9
  * - Brandsight / GoDaddy Corporate Domains: enterprise-contract-only, but
10
10
  * official v2 API supports portfolio, registration, renewal, nameserver,
11
11
  * and DNS operations.
12
- * - Cloudflare: DNS only (no registration) → always our DNS.
12
+ * - Cloudflare: DNS only (no registration) → common default DNS provider.
13
13
  * - Namecheap: buy + DNS via API (sandbox/whitelist required) → usable.
14
14
  */
15
15
  export interface ProviderCapability {
@@ -27,6 +27,6 @@ export declare function canBuy(name: string): boolean;
27
27
  * self-serve API). An explicit preference is honored only if it is non-gated.
28
28
  */
29
29
  export declare function selectBuyRegistrar(preference?: string): string;
30
- /** DNS is always Cloudflare, regardless of where the domain was bought. */
31
- export declare function selectDnsProvider(): string;
30
+ /** Choose a DNS provider, defaulting to Cloudflare when no preference is set. */
31
+ export declare function selectDnsProvider(preference?: string): string;
32
32
  //# sourceMappingURL=capability.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/lib/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAOpE,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAE9D;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ9D;AAED,2EAA2E;AAC3E,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C"}
1
+ {"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../../src/lib/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,iFAAiF;IACjF,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAOpE,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAE9D;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG5C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ9D;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ7D"}
@@ -31,7 +31,8 @@ export declare function createZone(domain: string, config?: CloudflareConfig): P
31
31
  /**
32
32
  * Find-or-create a Cloudflare zone and return its assigned nameservers.
33
33
  * Idempotent: reuses an existing zone for the domain if present. The returned
34
- * nameservers are what the registrar should be delegated to (always-Cloudflare).
34
+ * nameservers are what the registrar should be delegated to when Cloudflare is
35
+ * the selected DNS provider.
35
36
  *
36
37
  * `deps` is injectable for testing; defaults to the real getZone/createZone.
37
38
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/lib/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,uBAAuB,EAIxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAIjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,SAAS,IAAI,gBAAgB,CAE5C;AAqCD,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAkBpF;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQvG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAUnG;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,CAAC,EAAE;IACL,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7E,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E,GACA,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkBxG;AAkBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrH;AAyBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7G;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjI;AA4BD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,uBAAuB,CA+EzG"}
1
+ {"version":3,"file":"cloudflare.d.ts","sourceRoot":"","sources":["../../src/lib/cloudflare.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,WAAW,EACX,uBAAuB,EAIxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAIjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAID,wBAAgB,SAAS,IAAI,gBAAgB,CAE5C;AAqCD,wBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAkBpF;AAED,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQvG;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAUnG;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,gBAAgB,EACzB,IAAI,CAAC,EAAE;IACL,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC7E,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC1E,GACA,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzF;AAID,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAkBxG;AAkBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrH;AAyBD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE7G;AAED,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAQjI;AA4BD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,GAAG,uBAAuB,CA+EzG"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Persistent config stored at ~/.hasna/domains/config.json
2
+ * Persistent config stored in the domains config directory.
3
3
  */
4
4
  export interface DomainContact {
5
5
  first_name?: string;
@@ -21,9 +21,9 @@ export interface DomainsConfig {
21
21
  contact?: DomainContact;
22
22
  }
23
23
  /**
24
- * AWS profile to use for domain purchases. For this app, domains are bought in
25
- * the hasna-xyz-infra account. Resolved from config, then env. Applying it sets
26
- * process.env.AWS_PROFILE when no explicit AWS creds are already present.
24
+ * AWS profile to use for Route 53 domain purchases. Resolved from config, then
25
+ * env. Applying it sets process.env.AWS_PROFILE when no explicit AWS creds are
26
+ * already present.
27
27
  */
28
28
  export declare function getPurchaseProfile(): string | undefined;
29
29
  /** Set AWS_PROFILE from config for purchase ops if no explicit creds are set. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAKzD;AAMD,wBAAgB,UAAU,IAAI,aAAa,CAQ1C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAKtD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAe1E;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CAC9C,GAAG;IACF,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IACpE,cAAc,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAC1E,QAAQ,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9C,CA2BA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUhE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAIvD;AAED,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAKzD;AAYD,wBAAgB,UAAU,IAAI,aAAa,CAQ1C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAKtD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,CAe1E;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,IAAI,EAAE;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IACtD,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CAC9C,GAAG;IACF,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IACpE,cAAc,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAC1E,QAAQ,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9C,CA2BA;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAUhE"}
@@ -1 +1 @@
1
- {"version":3,"file":"creds-check.d.ts","sourceRoot":"","sources":["../../src/lib/creds-check.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAUD,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAqD,GAC1F,UAAU,EAAE,CA2Ed"}
1
+ {"version":3,"file":"creds-check.d.ts","sourceRoot":"","sources":["../../src/lib/creds-check.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAUD,wBAAgB,4BAA4B,CAC1C,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAqD,GAC1F,UAAU,EAAE,CA+Dd"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Cloudflare delegation the always-Cloudflare-DNS rule in one place.
2
+ * Cloudflare delegation helper for domains that should use Cloudflare DNS.
3
3
  *
4
4
  * After a domain is registered with ANY registrar, DNS is managed in Cloudflare:
5
5
  * create (or reuse) a Cloudflare zone, then point the registrar's nameservers at
@@ -16,27 +16,23 @@ export declare const GODADDY_ENV: {
16
16
  readonly apiSecret: readonly ["GODADDY_API_SECRET"];
17
17
  };
18
18
  export declare const BRANDSIGHT_ENV: {
19
- readonly apiKey: readonly ["BRANDSIGHT_API_KEY", "HASNAXYZ_BRANDSIGHT_LIVE_API_KEY", "HASNAXYZ_BRANDSIGHT_SANDBOX_API_KEY"];
20
- readonly apiSecret: readonly ["BRANDSIGHT_API_SECRET", "HASNAXYZ_BRANDSIGHT_LIVE_API_SECRET", "HASNAXYZ_BRANDSIGHT_SANDBOX_API_SECRET"];
21
- readonly customerId: readonly ["BRANDSIGHT_CUSTOMER_ID", "HASNAXYZ_BRANDSIGHT_LIVE_CUSTOMER_ID", "HASNAXYZ_BRANDSIGHT_SANDBOX_CUSTOMER_ID"];
22
- readonly shopperId: readonly ["BRANDSIGHT_SHOPPER_ID", "HASNAXYZ_BRANDSIGHT_LIVE_SHOPPER_ID", "HASNAXYZ_BRANDSIGHT_SANDBOX_SHOPPER_ID"];
23
- readonly accountId: readonly ["BRANDSIGHT_ACCOUNT_ID", "HASNAXYZ_BRANDSIGHT_LIVE_ACCOUNT_ID"];
19
+ readonly apiKey: readonly ["BRANDSIGHT_API_KEY"];
20
+ readonly apiSecret: readonly ["BRANDSIGHT_API_SECRET"];
21
+ readonly customerId: readonly ["BRANDSIGHT_CUSTOMER_ID"];
22
+ readonly shopperId: readonly ["BRANDSIGHT_SHOPPER_ID"];
23
+ readonly accountId: readonly ["BRANDSIGHT_ACCOUNT_ID"];
24
24
  };
25
25
  export declare const SEDO_ENV: {
26
- readonly partnerId: readonly ["SEDO_PARTNER_ID", "HASNAXYZ_SEDO_LIVE_PARTNER_ID"];
27
- readonly signKey: readonly ["SEDO_API_KEY", "SEDO_SIGN_KEY", "HASNAXYZ_SEDO_LIVE_API_KEY"];
28
- readonly username: readonly ["SEDO_USERNAME", "SEDO_EMAIL", "HASNAXYZ_SEDO_LIVE_USERNAME", "HASNAXYZ_SEDO_LIVE_EMAIL"];
29
- readonly password: readonly ["SEDO_PASSWORD", "HASNAXYZ_SEDO_LIVE_PASSWORD"];
26
+ readonly partnerId: readonly ["SEDO_PARTNER_ID"];
27
+ readonly signKey: readonly ["SEDO_API_KEY", "SEDO_SIGN_KEY"];
28
+ readonly username: readonly ["SEDO_USERNAME", "SEDO_EMAIL"];
29
+ readonly password: readonly ["SEDO_PASSWORD"];
30
30
  };
31
31
  export declare const CLOUDFLARE_ENV: {
32
- readonly apiToken: readonly ["CLOUDFLARE_API_TOKEN", "HASNAXYZ_CLOUDFLARE_LIVE_API_TOKEN"];
33
- readonly apiKey: readonly ["CLOUDFLARE_API_KEY", "HASNAXYZ_CLOUDFLARE_LIVE_API_KEY"];
34
- readonly email: readonly ["CLOUDFLARE_EMAIL", "HASNAXYZ_CLOUDFLARE_LIVE_EMAIL"];
35
- readonly accountId: readonly ["CLOUDFLARE_ACCOUNT_ID", "HASNAXYZ_CLOUDFLARE_LIVE_ACCOUNT_ID"];
36
- };
37
- export declare const BEEPMEDIA_AWS_ENV: {
38
- readonly accessKeyId: readonly ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_ACCESS_KEY_ID", "BEEPMEDIA_AWS_ACCESS_KEY_ID"];
39
- readonly secretAccessKey: readonly ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_SECRET_ACCESS_KEY", "BEEPMEDIA_AWS_SECRET_ACCESS_KEY"];
32
+ readonly apiToken: readonly ["CLOUDFLARE_API_TOKEN"];
33
+ readonly apiKey: readonly ["CLOUDFLARE_API_KEY"];
34
+ readonly email: readonly ["CLOUDFLARE_EMAIL"];
35
+ readonly accountId: readonly ["CLOUDFLARE_ACCOUNT_ID"];
40
36
  };
41
37
  export declare function providerEnvNames(provider: string): string[];
42
38
  export declare function hasProviderCredentials(provider: string, env?: Env): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"env-aliases.d.ts","sourceRoot":"","sources":["../../src/lib/env-aliases.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,GAAG,SAAS,CAMjF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAErF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,CAEhF;AAED,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;CAsBjB,CAAC;AAEX,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAyB3D;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,GAAwB,GAC5B,OAAO,CAsBT"}
1
+ {"version":3,"file":"env-aliases.d.ts","sourceRoot":"","sources":["../../src/lib/env-aliases.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAErD,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,GAAG,SAAS,CAMjF;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAErF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,CAEhF;AAED,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAEX,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AAEX,eAAO,MAAM,QAAQ;;;;;CAKX,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB3D;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,GAAwB,GAC5B,OAAO,CAoBT"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * NS drift reconciler — enforces the always-Cloudflare-DNS invariant across the
2
+ * NS drift reconciler — enforces Cloudflare DNS delegation for portfolios that choose it.
3
3
  * portfolio: every domain's nameservers must point to Cloudflare. Detects drift
4
4
  * (registrar NS not Cloudflare) and can re-delegate. Pure detection + an
5
5
  * injected reconcile loop, so it is fully testable.
@@ -96,9 +96,8 @@ type Route53DomainsSend = {
96
96
  /**
97
97
  * Point a domain's nameservers at a new set (the Cloudflare zone NS).
98
98
  *
99
- * Enforces the always-Cloudflare-DNS rule: after a domain is registered with
100
- * ANY registrar, delegate DNS to Cloudflare by calling this with the Cloudflare
101
- * zone's nameservers. Returns the async operation id (poll getOperationDetail).
99
+ * Point a Route 53-registered domain at the chosen DNS provider's nameservers.
100
+ * Returns the async operation id (poll getOperationDetail).
102
101
  */
103
102
  export declare function updateNameservers(domain: string, nameservers: string[], config?: Route53Config, client?: Route53DomainsSend): Promise<{
104
103
  operationId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"route53.d.ts","sourceRoot":"","sources":["../../src/lib/route53.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route53.d.ts","sourceRoot":"","sources":["../../src/lib/route53.ts"],"names":[],"mappings":"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"}
package/dist/mcp/index.js CHANGED
@@ -31395,20 +31395,26 @@ var MIGRATIONS = [
31395
31395
  // src/db/database.ts
31396
31396
  var _db = null;
31397
31397
  function getDbPath() {
31398
+ if (process.env["DOMAINS_DB_PATH"])
31399
+ return process.env["DOMAINS_DB_PATH"];
31398
31400
  if (process.env["HASNA_DOMAINS_DB_PATH"])
31399
31401
  return process.env["HASNA_DOMAINS_DB_PATH"];
31400
- const explicit = process.env["HASNA_DOMAINS_DIR"] ?? process.env["DOMAINS_DIR"];
31402
+ const explicit = process.env["DOMAINS_DIR"] ?? process.env["HASNA_DOMAINS_DIR"];
31401
31403
  if (explicit) {
31402
31404
  return join(explicit, "domains.db");
31403
31405
  }
31404
31406
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
31405
- migrateDotfile("domains");
31406
- return join(home, ".hasna", "domains", "domains.db");
31407
- }
31408
- function migrateDotfile(name) {
31407
+ const legacyDir = join(home, ".hasna", "domains");
31408
+ if (existsSync(legacyDir))
31409
+ return join(legacyDir, "domains.db");
31410
+ const xdgData = process.env["XDG_DATA_HOME"] || join(home, ".local", "share");
31411
+ const newDir = join(xdgData, "open-domains");
31412
+ migrateDotfile("domains", newDir);
31413
+ return join(newDir, "domains.db");
31414
+ }
31415
+ function migrateDotfile(name, newDir) {
31409
31416
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
31410
31417
  const oldDir = join(home, `.${name}`);
31411
- const newDir = join(home, ".hasna", name);
31412
31418
  if (!existsSync(oldDir) || existsSync(newDir))
31413
31419
  return;
31414
31420
  mkdirSync(newDir, { recursive: true });
@@ -39812,43 +39818,23 @@ var GODADDY_ENV = {
39812
39818
  apiSecret: ["GODADDY_API_SECRET"]
39813
39819
  };
39814
39820
  var BRANDSIGHT_ENV = {
39815
- apiKey: [
39816
- "BRANDSIGHT_API_KEY",
39817
- "HASNAXYZ_BRANDSIGHT_LIVE_API_KEY",
39818
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_KEY"
39819
- ],
39820
- apiSecret: [
39821
- "BRANDSIGHT_API_SECRET",
39822
- "HASNAXYZ_BRANDSIGHT_LIVE_API_SECRET",
39823
- "HASNAXYZ_BRANDSIGHT_SANDBOX_API_SECRET"
39824
- ],
39825
- customerId: [
39826
- "BRANDSIGHT_CUSTOMER_ID",
39827
- "HASNAXYZ_BRANDSIGHT_LIVE_CUSTOMER_ID",
39828
- "HASNAXYZ_BRANDSIGHT_SANDBOX_CUSTOMER_ID"
39829
- ],
39830
- shopperId: [
39831
- "BRANDSIGHT_SHOPPER_ID",
39832
- "HASNAXYZ_BRANDSIGHT_LIVE_SHOPPER_ID",
39833
- "HASNAXYZ_BRANDSIGHT_SANDBOX_SHOPPER_ID"
39834
- ],
39835
- accountId: ["BRANDSIGHT_ACCOUNT_ID", "HASNAXYZ_BRANDSIGHT_LIVE_ACCOUNT_ID"]
39821
+ apiKey: ["BRANDSIGHT_API_KEY"],
39822
+ apiSecret: ["BRANDSIGHT_API_SECRET"],
39823
+ customerId: ["BRANDSIGHT_CUSTOMER_ID"],
39824
+ shopperId: ["BRANDSIGHT_SHOPPER_ID"],
39825
+ accountId: ["BRANDSIGHT_ACCOUNT_ID"]
39836
39826
  };
39837
39827
  var SEDO_ENV = {
39838
- partnerId: ["SEDO_PARTNER_ID", "HASNAXYZ_SEDO_LIVE_PARTNER_ID"],
39839
- signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY", "HASNAXYZ_SEDO_LIVE_API_KEY"],
39840
- username: ["SEDO_USERNAME", "SEDO_EMAIL", "HASNAXYZ_SEDO_LIVE_USERNAME", "HASNAXYZ_SEDO_LIVE_EMAIL"],
39841
- password: ["SEDO_PASSWORD", "HASNAXYZ_SEDO_LIVE_PASSWORD"]
39828
+ partnerId: ["SEDO_PARTNER_ID"],
39829
+ signKey: ["SEDO_API_KEY", "SEDO_SIGN_KEY"],
39830
+ username: ["SEDO_USERNAME", "SEDO_EMAIL"],
39831
+ password: ["SEDO_PASSWORD"]
39842
39832
  };
39843
39833
  var CLOUDFLARE_ENV = {
39844
- apiToken: ["CLOUDFLARE_API_TOKEN", "HASNAXYZ_CLOUDFLARE_LIVE_API_TOKEN"],
39845
- apiKey: ["CLOUDFLARE_API_KEY", "HASNAXYZ_CLOUDFLARE_LIVE_API_KEY"],
39846
- email: ["CLOUDFLARE_EMAIL", "HASNAXYZ_CLOUDFLARE_LIVE_EMAIL"],
39847
- accountId: ["CLOUDFLARE_ACCOUNT_ID", "HASNAXYZ_CLOUDFLARE_LIVE_ACCOUNT_ID"]
39848
- };
39849
- var BEEPMEDIA_AWS_ENV = {
39850
- accessKeyId: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_ACCESS_KEY_ID", "BEEPMEDIA_AWS_ACCESS_KEY_ID"],
39851
- secretAccessKey: ["HASNASTUDIO_BEEPMEDIA_AWS_LIVE_SECRET_ACCESS_KEY", "BEEPMEDIA_AWS_SECRET_ACCESS_KEY"]
39834
+ apiToken: ["CLOUDFLARE_API_TOKEN"],
39835
+ apiKey: ["CLOUDFLARE_API_KEY"],
39836
+ email: ["CLOUDFLARE_EMAIL"],
39837
+ accountId: ["CLOUDFLARE_ACCOUNT_ID"]
39852
39838
  };
39853
39839
  function providerEnvNames(provider) {
39854
39840
  switch (provider.toLowerCase()) {
@@ -39870,8 +39856,6 @@ function providerEnvNames(provider) {
39870
39856
  return flattenEnvNames([CLOUDFLARE_ENV.apiToken, CLOUDFLARE_ENV.apiKey, CLOUDFLARE_ENV.email, CLOUDFLARE_ENV.accountId]);
39871
39857
  case "route53":
39872
39858
  return ["AWS_PROFILE", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION"];
39873
- case "aws:beepmedia":
39874
- return flattenEnvNames([BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
39875
39859
  default:
39876
39860
  return [];
39877
39861
  }
@@ -39893,8 +39877,6 @@ function hasProviderCredentials(provider, env = process.env) {
39893
39877
  }
39894
39878
  case "route53":
39895
39879
  return !!env["AWS_PROFILE"] || hasEveryEnv(env, [["AWS_ACCESS_KEY_ID"], ["AWS_SECRET_ACCESS_KEY"]]);
39896
- case "aws:beepmedia":
39897
- return hasEveryEnv(env, [BEEPMEDIA_AWS_ENV.accessKeyId, BEEPMEDIA_AWS_ENV.secretAccessKey]);
39898
39880
  default:
39899
39881
  return false;
39900
39882
  }
@@ -40170,7 +40152,7 @@ var _fetchFn = null;
40170
40152
  function getApiKey() {
40171
40153
  const key = resolveBrandsightConfig().apiKey;
40172
40154
  if (!key) {
40173
- throw new BrandsightApiError("Brandsight API key is not set. Set BRANDSIGHT_API_KEY or HASNAXYZ_BRANDSIGHT_LIVE_API_KEY.");
40155
+ throw new BrandsightApiError("Brandsight API key is not set. Set BRANDSIGHT_API_KEY.");
40174
40156
  }
40175
40157
  return key;
40176
40158
  }
@@ -40208,7 +40190,7 @@ async function apiGet(path, apiKey, baseUrl = BRANDSIGHT_BASE) {
40208
40190
  function requireDomainConfig(config) {
40209
40191
  const cfg = config ?? getConfig4();
40210
40192
  if (!cfg.apiKey || !cfg.apiSecret || !cfg.customerId) {
40211
- throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID (or HASNAXYZ_BRANDSIGHT_LIVE_* aliases).");
40193
+ throw new BrandsightApiError("Brandsight Domain API credentials are not configured. Set BRANDSIGHT_API_KEY, BRANDSIGHT_API_SECRET, and BRANDSIGHT_CUSTOMER_ID.");
40212
40194
  }
40213
40195
  return cfg;
40214
40196
  }
@@ -40924,9 +40906,18 @@ async function syncAll(dbFns) {
40924
40906
  // src/lib/config.ts
40925
40907
  import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
40926
40908
  import { homedir as homedir3 } from "os";
40927
- import { join as join3 } from "path";
40909
+ import { dirname as dirname4, join as join3 } from "path";
40928
40910
  function configPath() {
40929
- return join3(homedir3(), ".hasna", "domains", "config.json");
40911
+ if (process.env["DOMAINS_CONFIG_PATH"])
40912
+ return process.env["DOMAINS_CONFIG_PATH"];
40913
+ const dir = process.env["DOMAINS_CONFIG_DIR"];
40914
+ if (dir)
40915
+ return join3(dir, "config.json");
40916
+ const legacyDir = join3(homedir3(), ".hasna", "domains");
40917
+ if (existsSync2(legacyDir))
40918
+ return join3(legacyDir, "config.json");
40919
+ const xdgConfig = process.env["XDG_CONFIG_HOME"] || join3(homedir3(), ".config");
40920
+ return join3(xdgConfig, "open-domains", "config.json");
40930
40921
  }
40931
40922
  function loadConfig3() {
40932
40923
  const path = configPath();
@@ -41364,10 +41355,10 @@ var PRIMARY_KEYS = {
41364
41355
  domain_history: ["id"],
41365
41356
  domain_reputation: ["id"]
41366
41357
  };
41367
- var DOMAINS_STORAGE_ENV = "HASNA_DOMAINS_DATABASE_URL";
41368
- var DOMAINS_STORAGE_FALLBACK_ENV = "DOMAINS_DATABASE_URL";
41369
- var DOMAINS_STORAGE_MODE_ENV = "HASNA_DOMAINS_STORAGE_MODE";
41370
- var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "DOMAINS_STORAGE_MODE";
41358
+ var DOMAINS_STORAGE_ENV = "DOMAINS_DATABASE_URL";
41359
+ var DOMAINS_STORAGE_FALLBACK_ENV = "HASNA_DOMAINS_DATABASE_URL";
41360
+ var DOMAINS_STORAGE_MODE_ENV = "DOMAINS_STORAGE_MODE";
41361
+ var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "HASNA_DOMAINS_STORAGE_MODE";
41371
41362
  var STORAGE_DATABASE_ENV = [DOMAINS_STORAGE_ENV, DOMAINS_STORAGE_FALLBACK_ENV];
41372
41363
  var STORAGE_MODE_ENV = [DOMAINS_STORAGE_MODE_ENV, DOMAINS_STORAGE_MODE_FALLBACK_ENV];
41373
41364
  function firstEnv2(names) {
@@ -41395,7 +41386,7 @@ function getStorageMode() {
41395
41386
  async function getStoragePg() {
41396
41387
  const url = getStorageDatabaseUrl();
41397
41388
  if (!url) {
41398
- throw new Error("Missing HASNA_DOMAINS_DATABASE_URL or DOMAINS_DATABASE_URL");
41389
+ throw new Error("Missing DOMAINS_DATABASE_URL or HASNA_DOMAINS_DATABASE_URL");
41399
41390
  }
41400
41391
  return new PgAdapterAsync(url);
41401
41392
  }
@@ -41812,7 +41803,7 @@ function buildServer() {
41812
41803
  description: "Link an email or email thread to a tracked domain.",
41813
41804
  inputSchema: {
41814
41805
  domain: exports_external.string().describe("Domain ID or name"),
41815
- email_id: exports_external.string().describe("Email ID from @hasna/emails"),
41806
+ email_id: exports_external.string().describe("Email ID from the connected email system"),
41816
41807
  thread_id: exports_external.string().optional().describe("Optional email thread ID"),
41817
41808
  type: exports_external.enum(DOMAIN_EMAIL_TYPES)
41818
41809
  }
@@ -42574,7 +42565,7 @@ function buildServer() {
42574
42565
  zoneId = zone.id;
42575
42566
  nameservers = zone.nameservers ?? [];
42576
42567
  } else {
42577
- const zone = await createHostedZone(domain, "Managed by @hasna/domains");
42568
+ const zone = await createHostedZone(domain, "Managed by domains MCP");
42578
42569
  zoneId = zone.id;
42579
42570
  nameservers = zone.name_servers ?? [];
42580
42571
  }
package/dist/storage.js CHANGED
@@ -5355,20 +5355,26 @@ var MIGRATIONS = [
5355
5355
  // src/db/database.ts
5356
5356
  var _db = null;
5357
5357
  function getDbPath() {
5358
+ if (process.env["DOMAINS_DB_PATH"])
5359
+ return process.env["DOMAINS_DB_PATH"];
5358
5360
  if (process.env["HASNA_DOMAINS_DB_PATH"])
5359
5361
  return process.env["HASNA_DOMAINS_DB_PATH"];
5360
- const explicit = process.env["HASNA_DOMAINS_DIR"] ?? process.env["DOMAINS_DIR"];
5362
+ const explicit = process.env["DOMAINS_DIR"] ?? process.env["HASNA_DOMAINS_DIR"];
5361
5363
  if (explicit) {
5362
5364
  return join(explicit, "domains.db");
5363
5365
  }
5364
5366
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
5365
- migrateDotfile("domains");
5366
- return join(home, ".hasna", "domains", "domains.db");
5367
+ const legacyDir = join(home, ".hasna", "domains");
5368
+ if (existsSync(legacyDir))
5369
+ return join(legacyDir, "domains.db");
5370
+ const xdgData = process.env["XDG_DATA_HOME"] || join(home, ".local", "share");
5371
+ const newDir = join(xdgData, "open-domains");
5372
+ migrateDotfile("domains", newDir);
5373
+ return join(newDir, "domains.db");
5367
5374
  }
5368
- function migrateDotfile(name) {
5375
+ function migrateDotfile(name, newDir) {
5369
5376
  const home = process.env["HOME"] || process.env["USERPROFILE"] || homedir();
5370
5377
  const oldDir = join(home, `.${name}`);
5371
- const newDir = join(home, ".hasna", name);
5372
5378
  if (!existsSync(oldDir) || existsSync(newDir))
5373
5379
  return;
5374
5380
  mkdirSync(newDir, { recursive: true });
@@ -5442,10 +5448,10 @@ var PRIMARY_KEYS = {
5442
5448
  domain_history: ["id"],
5443
5449
  domain_reputation: ["id"]
5444
5450
  };
5445
- var DOMAINS_STORAGE_ENV = "HASNA_DOMAINS_DATABASE_URL";
5446
- var DOMAINS_STORAGE_FALLBACK_ENV = "DOMAINS_DATABASE_URL";
5447
- var DOMAINS_STORAGE_MODE_ENV = "HASNA_DOMAINS_STORAGE_MODE";
5448
- var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "DOMAINS_STORAGE_MODE";
5451
+ var DOMAINS_STORAGE_ENV = "DOMAINS_DATABASE_URL";
5452
+ var DOMAINS_STORAGE_FALLBACK_ENV = "HASNA_DOMAINS_DATABASE_URL";
5453
+ var DOMAINS_STORAGE_MODE_ENV = "DOMAINS_STORAGE_MODE";
5454
+ var DOMAINS_STORAGE_MODE_FALLBACK_ENV = "HASNA_DOMAINS_STORAGE_MODE";
5449
5455
  var STORAGE_DATABASE_ENV = [DOMAINS_STORAGE_ENV, DOMAINS_STORAGE_FALLBACK_ENV];
5450
5456
  var STORAGE_MODE_ENV = [DOMAINS_STORAGE_MODE_ENV, DOMAINS_STORAGE_MODE_FALLBACK_ENV];
5451
5457
  function firstEnv(names) {
@@ -5480,7 +5486,7 @@ function getStorageMode() {
5480
5486
  async function getStoragePg() {
5481
5487
  const url = getStorageDatabaseUrl();
5482
5488
  if (!url) {
5483
- throw new Error("Missing HASNA_DOMAINS_DATABASE_URL or DOMAINS_DATABASE_URL");
5489
+ throw new Error("Missing DOMAINS_DATABASE_URL or HASNA_DOMAINS_DATABASE_URL");
5484
5490
  }
5485
5491
  return new PgAdapterAsync(url);
5486
5492
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/domains",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "Domain portfolio and DNS management for AI agents — CLI + MCP server with SQLite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,7 +32,7 @@
32
32
  "dev:cli": "bun run src/cli/index.ts",
33
33
  "dev:mcp": "bun run src/mcp/index.ts",
34
34
  "prepublishOnly": "bun run build",
35
- "postinstall": "mkdir -p $HOME/.hasna/domains 2>/dev/null || true"
35
+ "postinstall": "mkdir -p ${XDG_DATA_HOME:-$HOME/.local/share}/open-domains ${XDG_CONFIG_HOME:-$HOME/.config}/open-domains 2>/dev/null || true"
36
36
  },
37
37
  "keywords": [
38
38
  "domains",