bulletin-deploy 0.13.2-rc.2 → 0.13.2-rc.4

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 (43) hide show
  1. package/bin/bulletin-deploy +56 -18
  2. package/dist/auth-config.js +3 -3
  3. package/dist/bug-report.js +4 -4
  4. package/dist/{chunk-IELQ4GO6.js → chunk-3NC5NB3F.js} +12 -8
  5. package/dist/{chunk-XIMLHQX5.js → chunk-AYDNHTZS.js} +4 -3
  6. package/dist/{chunk-A33TZ7T6.js → chunk-B5I6HOH7.js} +3 -3
  7. package/dist/{chunk-46BS77ZZ.js → chunk-C65GAMEI.js} +17 -1
  8. package/dist/{chunk-G7Y7QZIE.js → chunk-DZJ5QWTB.js} +1 -1
  9. package/dist/{chunk-P7MXONT2.js → chunk-L53JPHIS.js} +1 -1
  10. package/dist/{chunk-PEJQIIGR.js → chunk-MWRGXOVM.js} +32 -9
  11. package/dist/{chunk-DPSGCV2F.js → chunk-SBO6DAYU.js} +2 -2
  12. package/dist/{chunk-XOVXFR6G.js → chunk-SKBROFBP.js} +1 -1
  13. package/dist/{chunk-MYQO2UNZ.js → chunk-TU7PXMIV.js} +28 -11
  14. package/dist/{chunk-362JEZKM.js → chunk-U2SZ3ZRI.js} +29 -6
  15. package/dist/{chunk-PMYMVWFT.js → chunk-YQIB777Z.js} +1 -1
  16. package/dist/chunk-probe.js +3 -3
  17. package/dist/commands/login.js +10 -10
  18. package/dist/commands/logout.js +4 -4
  19. package/dist/commands/transfer.js +3 -3
  20. package/dist/commands/whoami.js +3 -3
  21. package/dist/deploy-actors.js +5 -5
  22. package/dist/deploy.d.ts +65 -1
  23. package/dist/deploy.js +22 -12
  24. package/dist/dotns.d.ts +9 -1
  25. package/dist/dotns.js +7 -3
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +14 -12
  28. package/dist/manifest/config-load.d.ts +9 -1
  29. package/dist/manifest/config-load.js +3 -1
  30. package/dist/manifest/publish.d.ts +6 -2
  31. package/dist/manifest/publish.js +11 -11
  32. package/dist/memory-report.js +2 -2
  33. package/dist/merkle.js +10 -10
  34. package/dist/personhood/bootstrap.js +3 -3
  35. package/dist/personhood/people-client.js +3 -3
  36. package/dist/run-state.js +1 -1
  37. package/dist/sss-allowance-cache.js +4 -4
  38. package/dist/storage-signer.js +10 -10
  39. package/dist/telemetry.d.ts +3 -2
  40. package/dist/telemetry.js +4 -2
  41. package/dist/version-check.js +3 -3
  42. package/package.json +4 -3
  43. package/tools/verify-baked-dsn.mjs +85 -0
@@ -6,7 +6,7 @@
6
6
  // SDK modules that trigger the "@parity/product-sdk-logger" localStorage warning.
7
7
  import "../dist/suppress-localstorage-warning.js";
8
8
 
9
- import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY, isConnectionError, isBenignTeardownError, unpublish, resolveEffectiveMnemonic } from "../dist/deploy.js";
9
+ import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY, isConnectionError, isBenignTeardownError, unpublish, resolveEffectiveMnemonic, resolveEnvId, shouldPublishManifest, validateNoManifestFlags } from "../dist/deploy.js";
10
10
  import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStateActive, markRelaunchOomHintShown } from "../dist/telemetry.js";
11
11
  import { handleFailedDeploy, handlePreflightVersionCheck, fetchVersionInfo, preReleaseWarning, checkNodeVersion } from "../dist/version-check.js";
12
12
  import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
@@ -56,6 +56,7 @@ for (let i = 0; i < args.length; i++) {
56
56
  else if (args[i] === "--input-car") { flags.inputCar = args[++i]; }
57
57
  else if (args[i] === "--tag") { flags.tag = args[++i]; }
58
58
  else if (args[i] === "--config") { flags.config = args[++i]; }
59
+ else if (args[i] === "--no-manifest" || args[i] === "--content-only") { flags.noManifest = true; }
59
60
  else if (args[i] === "--gh-pages-mirror") { flags.ghPagesMirror = true; }
60
61
  else if (args[i] === "--allow-large-deploy") { flags.allowLargeDeploy = true; }
61
62
  else if (args[i] === "--reproducible") { flags.reproducibleSource = "commit"; }
@@ -78,6 +79,16 @@ if (flags.publish && flags.unpublish) {
78
79
  process.exit(1);
79
80
  }
80
81
 
82
+ // #1163: --no-manifest (--content-only) skips manifest publishing even when a
83
+ // bulletin-deploy.config.* is discoverable; --publish depends on those
84
+ // manifest records (Publisher listing → Browse), so the combination is
85
+ // rejected up front rather than silently publishing a domain with no manifest.
86
+ const noManifestErr = validateNoManifestFlags({ noManifest: !!flags.noManifest, publish: !!flags.publish });
87
+ if (noManifestErr) {
88
+ console.error(noManifestErr);
89
+ process.exit(1);
90
+ }
91
+
81
92
  // #1107: the mnemonic actually used to sign — --mnemonic flag > MNEMONIC env
82
93
  // var > DOTNS_MNEMONIC env var. Used everywhere deploy/publish/unpublish need
83
94
  // a signer identity (existence guards below intentionally keep checking
@@ -89,6 +100,13 @@ const effectiveMnemonic = resolveEffectiveMnemonic({
89
100
  envDotnsMnemonic: process.env.DOTNS_MNEMONIC,
90
101
  });
91
102
 
103
+ // #1165: the env id actually targeted this session — --env flag >
104
+ // BULLETIN_DEPLOY_ENV env var. `undefined` here still means "let
105
+ // deploy()/the DEFAULT_ENV_ID fallback below decide" — this only resolves
106
+ // the flag/env-var precedence so a session default doesn't require
107
+ // repeating --env on every invocation.
108
+ const effectiveEnvId = resolveEnvId({ flagEnv: flags.env, envVar: process.env.BULLETIN_DEPLOY_ENV });
109
+
92
110
  // --environment-file: propagate to the env var so all internal loadEnvironments()
93
111
  // call sites (deploy.ts, manifest/publish.ts, personhood) honor the override.
94
112
  if (flags.environmentFile) {
@@ -133,7 +151,7 @@ if (flags.unpublish) {
133
151
  mnemonic: effectiveMnemonic,
134
152
  derivationPath: flags.derivationPath,
135
153
  rpc: flags.rpc,
136
- env: flags.env,
154
+ env: effectiveEnvId,
137
155
  });
138
156
  console.log(`Domain: ${result.domainName}`);
139
157
  console.log(`Status: ${result.status}`);
@@ -159,7 +177,7 @@ function installSsoTeardownGuards() {
159
177
  {
160
178
  const sub = positional[0];
161
179
  if (sub === "login" || sub === "logout" || sub === "whoami") {
162
- const envId = flags.env ?? DEFAULT_ENV_ID;
180
+ const envId = effectiveEnvId ?? DEFAULT_ENV_ID;
163
181
  installSsoTeardownGuards();
164
182
  try {
165
183
  const capSub = sub.charAt(0).toUpperCase() + sub.slice(1);
@@ -178,7 +196,7 @@ function installSsoTeardownGuards() {
178
196
  // (or --to). Stand-alone handover + recovery for a deploy whose transfer step
179
197
  // failed. Uses the SSO stack to resolve the session recipient.
180
198
  if (positional[0] === "transfer") {
181
- const envId = flags.env ?? DEFAULT_ENV_ID;
199
+ const envId = effectiveEnvId ?? DEFAULT_ENV_ID;
182
200
  installSsoTeardownGuards();
183
201
  try {
184
202
  const { runTransfer } = await import("../dist/commands/transfer.js");
@@ -248,6 +266,9 @@ Options:
248
266
  --env <id> Target environment from environments.json (default: paseo-next-v2).
249
267
  Drives both the bulletin RPC and the asset-hub RPC used
250
268
  by DotNS. See --list-environments for valid ids.
269
+ Precedence: --env > BULLETIN_DEPLOY_ENV env var > paseo-next-v2.
270
+ Set BULLETIN_DEPLOY_ENV to pick a session default without
271
+ repeating --env on every invocation.
251
272
  --environment-file <path>
252
273
  Path to a JSON file deep-merged over the bundled
253
274
  environments.json. Override only the fields you need
@@ -285,6 +306,11 @@ Options:
285
306
  <build-dir> looking for bulletin-deploy.config.{ts,js,mjs}). When a
286
307
  config is found, deploy ALSO writes the manifest + executable text
287
308
  records on <domain> and its app/widget/worker subnames.
309
+ --no-manifest, --content-only
310
+ Skip manifest publishing entirely, even when a
311
+ bulletin-deploy.config.* is discoverable — plain content
312
+ deploy (storage + root contenthash), same as having no
313
+ config at all. Mutually exclusive with --publish.
288
314
  --gh-pages-mirror After deploy, push the CAR to the current repo's gh-pages branch
289
315
  at bulletin/<domain>.dot.car (opt-in; also set GH_PAGES_MIRROR=1)
290
316
  --publish After deploy, list <domain> in the on-chain Publisher
@@ -471,16 +497,22 @@ try {
471
497
  // + its referenced icon/executable files BEFORE any storage or chain work, so
472
498
  // config errors fail fast up front instead of after merkleize + upload. No-op
473
499
  // (returns null) for contenthash-only deploys with no config.
474
- try {
475
- const { preflightProductConfig } = await import("../dist/index.js");
476
- // config-load resolves a relative cwd internally, so no node:path here
477
- // (it's only dynamically imported later, in the publish block).
478
- await preflightProductConfig(
479
- flags.config ? { path: flags.config } : { cwd: buildDir, walkUp: true },
480
- );
481
- } catch (err) {
482
- console.error(`Error: ${err?.message ?? err}`);
483
- process.exit(err instanceof NonRetryableError ? EXIT_CODE_NO_RETRY : 1);
500
+ //
501
+ // #1163: --no-manifest (--content-only) skips this entirely — the deploy is
502
+ // content-only regardless of any discoverable config, so there's nothing to
503
+ // preflight.
504
+ if (!flags.noManifest) {
505
+ try {
506
+ const { preflightProductConfig } = await import("../dist/index.js");
507
+ // config-load resolves a relative cwd internally, so no node:path here
508
+ // (it's only dynamically imported later, in the publish block).
509
+ await preflightProductConfig(
510
+ flags.config ? { path: flags.config } : { cwd: buildDir, walkUp: true },
511
+ );
512
+ } catch (err) {
513
+ console.error(`Error: ${err?.message ?? err}`);
514
+ process.exit(err instanceof NonRetryableError ? EXIT_CODE_NO_RETRY : 1);
515
+ }
484
516
  }
485
517
 
486
518
  const result = await deploy(buildDir, domain, {
@@ -488,7 +520,7 @@ try {
488
520
  derivationPath: flags.derivationPath,
489
521
  suri: flags.suri,
490
522
  rpc: flags.rpc,
491
- env: flags.env,
523
+ env: effectiveEnvId,
492
524
  poolSize: flags.poolSize,
493
525
  password: flags.password,
494
526
  contracts: flags.contracts,
@@ -553,6 +585,12 @@ try {
553
585
  // Walks up from <build-dir> (or honours --config) looking for
554
586
  // bulletin-deploy.config.{ts,js,mjs}. When found, writes the root + per-
555
587
  // executable text records, otherwise the legacy flow returns unchanged.
588
+ //
589
+ // #1163: --no-manifest (--content-only) skips manifest publishing even when
590
+ // a config is present. shouldPublishManifest() is the single source of
591
+ // truth for that decision (config discovery still runs either way, so the
592
+ // "config found but --no-manifest set" case is exercised for real, not just
593
+ // in unit tests).
556
594
  {
557
595
  const { tryLoadProductConfig, publishManifest } = await import("../dist/index.js");
558
596
  const path = await import("node:path");
@@ -560,13 +598,13 @@ try {
560
598
  const loaded = await tryLoadProductConfig(
561
599
  flags.config ? { path: flags.config } : { cwd: buildDirAbs, walkUp: true },
562
600
  );
563
- if (loaded) {
601
+ if (shouldPublishManifest({ configFound: !!loaded, noManifest: !!flags.noManifest })) {
564
602
  try {
565
603
  await publishManifest({
566
604
  loaded,
567
605
  domain,
568
606
  buildDirCid: { absPath: buildDirAbs, cid: result.cid },
569
- env: flags.env,
607
+ env: effectiveEnvId,
570
608
  rpc: flags.rpc,
571
609
  mnemonic: effectiveMnemonic,
572
610
  derivationPath: flags.derivationPath,
@@ -576,7 +614,7 @@ try {
576
614
  process.exit(err instanceof NonRetryableError ? EXIT_CODE_NO_RETRY : 1);
577
615
  }
578
616
  }
579
- // No config → the contenthash-only deploy above is the whole job; nothing else to do.
617
+ // No config (or --no-manifest) → the contenthash-only deploy above is the whole job; nothing else to do.
580
618
  }
581
619
 
582
620
  if (!flags.help && !flags.version) {
@@ -9,10 +9,10 @@ import {
9
9
  getPeopleChainEndpoints,
10
10
  hasPersistedSession,
11
11
  resolveBulletinEndpoints
12
- } from "./chunk-P7MXONT2.js";
12
+ } from "./chunk-L53JPHIS.js";
13
13
  import "./chunk-TSPERKUS.js";
14
- import "./chunk-MYQO2UNZ.js";
15
- import "./chunk-XIMLHQX5.js";
14
+ import "./chunk-TU7PXMIV.js";
15
+ import "./chunk-AYDNHTZS.js";
16
16
  import "./chunk-3ZEMX4WD.js";
17
17
  import "./chunk-ZOC4GITL.js";
18
18
  export {
@@ -10,10 +10,10 @@ import {
10
10
  offerBugReport,
11
11
  scrubSecrets,
12
12
  setDeployContext
13
- } from "./chunk-A33TZ7T6.js";
14
- import "./chunk-XOVXFR6G.js";
15
- import "./chunk-MYQO2UNZ.js";
16
- import "./chunk-XIMLHQX5.js";
13
+ } from "./chunk-B5I6HOH7.js";
14
+ import "./chunk-SKBROFBP.js";
15
+ import "./chunk-TU7PXMIV.js";
16
+ import "./chunk-AYDNHTZS.js";
17
17
  export {
18
18
  buildCliFlagsSummary,
19
19
  buildLabels,
@@ -4,14 +4,17 @@ import {
4
4
  import {
5
5
  BLAKE2B_256_MULTIHASH_CODE,
6
6
  encodeContenthash,
7
+ resolveBulletinEndpoints,
7
8
  resolveDotnsConnectOptions,
9
+ setBulletinEndpoints,
8
10
  storeDirectory,
9
11
  storeFile
10
- } from "./chunk-PEJQIIGR.js";
12
+ } from "./chunk-MWRGXOVM.js";
11
13
  import {
12
14
  DotNS
13
- } from "./chunk-46BS77ZZ.js";
15
+ } from "./chunk-C65GAMEI.js";
14
16
  import {
17
+ DEFAULT_ENV_ID,
15
18
  getPopSelfServeConfig,
16
19
  loadEnvironments,
17
20
  resolveEndpoints
@@ -38,6 +41,11 @@ async function publishManifest(opts) {
38
41
  );
39
42
  }
40
43
  const configDir = path.dirname(sourcePath);
44
+ const envId = opts.env ?? DEFAULT_ENV_ID;
45
+ const { doc } = await loadEnvironments();
46
+ const resolved = resolveEndpoints(doc, envId);
47
+ const popSelfServe = getPopSelfServeConfig(doc, envId);
48
+ setBulletinEndpoints(resolveBulletinEndpoints(resolved.bulletin, opts.rpc));
41
49
  const iconAbs = path.resolve(configDir, config.icon.path);
42
50
  const iconBytes = await readFileOrThrow(iconAbs, "icon");
43
51
  console.log(`
@@ -59,7 +67,7 @@ Manifest publish \u2014 ${config.domain}`);
59
67
  console.log(` Executable [${exec.kind}] CID: ${storageCid}`);
60
68
  executableCids[exec.kind] = storageCid;
61
69
  }
62
- const dotns = await connectDotNS(opts);
70
+ const dotns = await connectDotNS(opts, resolved, popSelfServe, envId);
63
71
  try {
64
72
  const baseLabel = stripDotSuffix(config.domain);
65
73
  await dotns.ensureContentResolver(baseLabel);
@@ -104,11 +112,7 @@ async function readFileOrThrow(p, label) {
104
112
  throw new NonRetryableError(`Cannot read ${label} at ${p}: ${err.message}`);
105
113
  }
106
114
  }
107
- async function connectDotNS(opts) {
108
- const envId = opts.env ?? "paseo-next-v2";
109
- const { doc } = await loadEnvironments();
110
- const resolved = resolveEndpoints(doc, envId);
111
- const popSelfServe = getPopSelfServeConfig(doc, envId);
115
+ async function connectDotNS(opts, resolved, popSelfServe, envId) {
112
116
  const deployOptsShim = {
113
117
  mnemonic: opts.mnemonic,
114
118
  derivationPath: opts.derivationPath
@@ -6,7 +6,7 @@ import * as path from "path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bulletin-deploy",
9
- version: "0.13.2-rc.2",
9
+ version: "0.13.2-rc.4",
10
10
  private: false,
11
11
  repository: {
12
12
  type: "git",
@@ -48,14 +48,15 @@ var package_default = {
48
48
  "assets",
49
49
  "patches",
50
50
  "DEPLOYMENT.md",
51
- "tools/release-retry-wrapper.mjs"
51
+ "tools/release-retry-wrapper.mjs",
52
+ "tools/verify-baked-dsn.mjs"
52
53
  ],
53
54
  scripts: {
54
55
  build: "tsup src/suppress-localstorage-warning.ts src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/memory-report.ts src/merkle.ts src/gh-pages-mirror.ts src/version-check.ts src/bug-report.ts src/run-state.ts src/environments.ts src/errors.ts src/manifest.ts src/chunk-probe.ts src/manifest-embed.ts src/manifest-fetch.ts src/manifest-roundtrip.ts src/incremental-stats.ts src/chunker.ts src/personhood/encoding.ts src/personhood/hashing.ts src/personhood/constants.ts src/personhood/member-key.ts src/personhood/people-client.ts src/personhood/proof-validity.ts src/personhood/reprove.ts src/personhood/bind-personal-id.ts src/personhood/claim-pgas.ts src/personhood/bind-paid-alias.ts src/personhood/bootstrap.ts src/personhood/chain-prereqs.ts src/manifest/types.ts src/manifest/schema.ts src/manifest/byte-budget.ts src/manifest/config-load.ts src/manifest/publish.ts src/auth/index.ts src/auth/vendor/index.ts src/auth/vendor/ui/index.ts src/auth-config.ts src/commands/login.ts src/commands/logout.ts src/commands/whoami.ts src/commands/transfer.ts src/storage-signer.ts src/spinner.ts src/sss-allowance.ts src/sss-allowance-cache.ts src/deploy-actors.ts --format esm --dts --clean --target node22",
55
56
  "refresh-environments": "node scripts/refresh-environments.mjs",
56
57
  postinstall: "patch-package || true",
57
58
  prepare: "npm run build",
58
- test: "npm run build && node --test test/test.js test/cli-help.test.js test/helpers/e2e-helpers.test.js test/environments.test.js test/refresh-environments.test.js test/chunk-sharing-report.test.js test/product-manifest.test.js test/cache-savings-totals.test.js test/error-pattern-signature.test.js test/exit-codes.test.js test/probe-env-health.test.js test/e2e-chain-calls.test.js test/auth-config.test.js test/whoami.test.js test/login.test.js test/logout.test.js test/auth-resolve.test.js test/storage-signer.test.js test/spinner.test.js test/sss-allowance.test.js test/sss-allowance-cache.test.js test/dotns-transfer.test.js test/deploy-actors.test.js test/transfer-command.test.js test/dotns-register-fee.test.js test/deploy-label-ordering.test.js test/benign-teardown.test.js && npm run test:vendor",
59
+ test: "npm run build && node --test test/test.js test/cli-help.test.js test/helpers/e2e-helpers.test.js test/environments.test.js test/refresh-environments.test.js test/chunk-sharing-report.test.js test/product-manifest.test.js test/cache-savings-totals.test.js test/error-pattern-signature.test.js test/exit-codes.test.js test/probe-env-health.test.js test/e2e-chain-calls.test.js test/auth-config.test.js test/whoami.test.js test/login.test.js test/logout.test.js test/auth-resolve.test.js test/storage-signer.test.js test/spinner.test.js test/sss-allowance.test.js test/sss-allowance-cache.test.js test/dotns-transfer.test.js test/deploy-actors.test.js test/transfer-command.test.js test/dotns-register-fee.test.js test/deploy-label-ordering.test.js test/benign-teardown.test.js test/verify-baked-dsn.test.js && npm run test:vendor",
59
60
  "test:e2e": "npm run build && node --test test/e2e.test.js",
60
61
  "test:e2e:smoke": "bash scripts/e2e-pass.sh smoke",
61
62
  "test:e2e:pr": "bash scripts/e2e-pass.sh pr",
@@ -2,15 +2,15 @@ import {
2
2
  classifyErrorArea,
3
3
  isInteractive,
4
4
  promptYesNo
5
- } from "./chunk-XOVXFR6G.js";
5
+ } from "./chunk-SKBROFBP.js";
6
6
  import {
7
7
  VERSION,
8
8
  getCurrentSentryTraceId,
9
9
  resolveIssueRepoSlug
10
- } from "./chunk-MYQO2UNZ.js";
10
+ } from "./chunk-TU7PXMIV.js";
11
11
  import {
12
12
  package_default
13
- } from "./chunk-XIMLHQX5.js";
13
+ } from "./chunk-AYDNHTZS.js";
14
14
 
15
15
  // src/bug-report.ts
16
16
  import { execSync, execFileSync } from "child_process";
@@ -11,7 +11,7 @@ import {
11
11
  setDeploySentryTag,
12
12
  truncateAddress,
13
13
  withSpan
14
- } from "./chunk-MYQO2UNZ.js";
14
+ } from "./chunk-TU7PXMIV.js";
15
15
  import {
16
16
  validateContractAddresses
17
17
  } from "./chunk-3ZEMX4WD.js";
@@ -63,6 +63,10 @@ var TX_KIND_HASH = "hash";
63
63
  var TX_KIND_NONCE_ADVANCED = "nonce-advanced";
64
64
  var TX_KIND_BEST_BLOCK = "best-block";
65
65
  var ATTR_TX_RESOLUTION_KIND = "deploy.dotns.tx_resolution_kind";
66
+ var TX_KIND_SKIPPED = "skipped";
67
+ function shouldSkipTextWrite(current, target) {
68
+ return current === target;
69
+ }
66
70
  var ONE_PAS = 10000000000n;
67
71
  var FEE_FLOOR_OWNED = ONE_PAS / 100n;
68
72
  var FEE_FLOOR_REGISTER = ONE_PAS / 10n;
@@ -2031,6 +2035,16 @@ var DotNS = class {
2031
2035
  this.ensureConnected();
2032
2036
  console.log(` Setting text[${key}]: ${value}`);
2033
2037
  const node = namehash(`${domainName}.dot`);
2038
+ try {
2039
+ const current = await this.getTextRecord(domainName, key);
2040
+ if (shouldSkipTextWrite(current, value)) {
2041
+ console.log(` text[${key}] already set \u2014 skipping tx`);
2042
+ setDeployAttribute("deploy.dotns.text_unchanged", "true");
2043
+ return { value, txHash: TX_KIND_SKIPPED };
2044
+ }
2045
+ } catch (_) {
2046
+ }
2047
+ setDeployAttribute("deploy.dotns.text_unchanged", "false");
2034
2048
  const MAX_VERIFY_CHAIN_SECONDS = VERIFY_EFFECT_CHAIN_SECONDS;
2035
2049
  const TEXT_POLL_INTERVAL_MS = 2e3;
2036
2050
  const verifyEffect = async () => {
@@ -2948,6 +2962,8 @@ export {
2948
2962
  TX_KIND_NONCE_ADVANCED,
2949
2963
  TX_KIND_BEST_BLOCK,
2950
2964
  ATTR_TX_RESOLUTION_KIND,
2965
+ TX_KIND_SKIPPED,
2966
+ shouldSkipTextWrite,
2951
2967
  MINIMUM_REGISTER_STORAGE_DEPOSIT,
2952
2968
  registerDepositWei,
2953
2969
  bufferedWeiToNative,
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-GRPLHUYC.js";
4
4
  import {
5
5
  DOT_DAPP_ID
6
- } from "./chunk-P7MXONT2.js";
6
+ } from "./chunk-L53JPHIS.js";
7
7
 
8
8
  // src/sss-allowance-cache.ts
9
9
  import { mkdir, readFile, writeFile, unlink } from "fs/promises";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-TSPERKUS.js";
4
4
  import {
5
5
  VERSION
6
- } from "./chunk-MYQO2UNZ.js";
6
+ } from "./chunk-TU7PXMIV.js";
7
7
  import {
8
8
  loadEnvironments
9
9
  } from "./chunk-3ZEMX4WD.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  preflightSssAllowance
3
- } from "./chunk-G7Y7QZIE.js";
3
+ } from "./chunk-DZJ5QWTB.js";
4
4
  import {
5
5
  statementSigningAccount
6
6
  } from "./chunk-GRPLHUYC.js";
@@ -31,18 +31,18 @@ import {
31
31
  } from "./chunk-S7EM5VMW.js";
32
32
  import {
33
33
  setDeployContext
34
- } from "./chunk-A33TZ7T6.js";
34
+ } from "./chunk-B5I6HOH7.js";
35
35
  import {
36
36
  getBestBlockNumber,
37
37
  probeChunks,
38
38
  probeFinalityGap
39
- } from "./chunk-PMYMVWFT.js";
39
+ } from "./chunk-YQIB777Z.js";
40
40
  import {
41
41
  packSection
42
42
  } from "./chunk-C2TS5MER.js";
43
43
  import {
44
44
  resolveStorageSigner
45
- } from "./chunk-DPSGCV2F.js";
45
+ } from "./chunk-SBO6DAYU.js";
46
46
  import {
47
47
  createSlotAccountSigner,
48
48
  requestResourceAllocation
@@ -51,7 +51,7 @@ import {
51
51
  STALE_SESSION_MESSAGE,
52
52
  getPeopleChainEndpoints,
53
53
  hasPersistedSession
54
- } from "./chunk-P7MXONT2.js";
54
+ } from "./chunk-L53JPHIS.js";
55
55
  import {
56
56
  CLI_NAME
57
57
  } from "./chunk-TSPERKUS.js";
@@ -64,7 +64,7 @@ import {
64
64
  parseDomainName,
65
65
  popStatusName,
66
66
  verifyNonceAdvanced
67
- } from "./chunk-46BS77ZZ.js";
67
+ } from "./chunk-C65GAMEI.js";
68
68
  import {
69
69
  derivePoolAccounts,
70
70
  detectTestnet,
@@ -86,7 +86,7 @@ import {
86
86
  truncateAddress,
87
87
  withDeploySpan,
88
88
  withSpan
89
- } from "./chunk-MYQO2UNZ.js";
89
+ } from "./chunk-TU7PXMIV.js";
90
90
  import {
91
91
  DEFAULT_ENV_ID,
92
92
  getPopSelfServeConfig,
@@ -406,6 +406,13 @@ var DEFAULT_BULLETIN_RPC = "wss://paseo-bulletin-rpc.polkadot.io";
406
406
  var DEFAULT_POOL_SIZE = 10;
407
407
  var BULLETIN_ENDPOINTS = [DEFAULT_BULLETIN_RPC];
408
408
  var POOL_SIZE = DEFAULT_POOL_SIZE;
409
+ function resolveBulletinEndpoints(envBulletin, rpcOverride) {
410
+ const userRpc = rpcOverride ?? process.env.BULLETIN_RPC;
411
+ return userRpc ? [userRpc, ...envBulletin.filter((e) => e !== userRpc)] : envBulletin;
412
+ }
413
+ function setBulletinEndpoints(endpoints) {
414
+ BULLETIN_ENDPOINTS = endpoints;
415
+ }
409
416
  var bulletinAutoAuthorize = false;
410
417
  var _deployRpcFailedOver = false;
411
418
  var _onWsHalt = null;
@@ -644,6 +651,18 @@ function __selectStorageProviderModeForTest(options) {
644
651
  function resolveEffectiveMnemonic(opts) {
645
652
  return opts.flagMnemonic ?? opts.envMnemonic ?? opts.envDotnsMnemonic;
646
653
  }
654
+ function resolveEnvId(opts) {
655
+ return opts.flagEnv ?? opts.envVar;
656
+ }
657
+ function shouldPublishManifest(opts) {
658
+ return opts.configFound && !opts.noManifest;
659
+ }
660
+ function validateNoManifestFlags(opts) {
661
+ if (opts.noManifest && opts.publish) {
662
+ return "Error: --no-manifest (--content-only) and --publish are mutually exclusive \u2014 --publish requires the manifest records that --no-manifest skips.";
663
+ }
664
+ return null;
665
+ }
647
666
  function chooseSignerInput(opts) {
648
667
  if (opts.mnemonic) return "mnemonic";
649
668
  if (opts.hasInjectedSigner) return "injected";
@@ -2128,8 +2147,7 @@ async function deploy(content, domainName = null, options = {}) {
2128
2147
  if (options.contracts && Object.keys(options.contracts).length > 0) {
2129
2148
  envContracts = { ...envContracts, ...options.contracts };
2130
2149
  }
2131
- const userRpc = options.rpc ?? process.env.BULLETIN_RPC;
2132
- BULLETIN_ENDPOINTS = userRpc ? [userRpc, ...envBulletin.filter((e) => e !== userRpc)] : envBulletin;
2150
+ BULLETIN_ENDPOINTS = resolveBulletinEndpoints(envBulletin, options.rpc);
2133
2151
  _deployRpcFailedOver = false;
2134
2152
  POOL_SIZE = options.poolSize ?? parseInt(process.env.BULLETIN_POOL_SIZE ?? String(DEFAULT_POOL_SIZE), 10);
2135
2153
  const parsed = domainName ? parseDomainName(domainName) : null;
@@ -3116,6 +3134,8 @@ export {
3116
3134
  DEFAULT_BULLETIN_RPC,
3117
3135
  DEFAULT_POOL_SIZE,
3118
3136
  BULLETIN_ENDPOINTS,
3137
+ resolveBulletinEndpoints,
3138
+ setBulletinEndpoints,
3119
3139
  setWsHaltCallback,
3120
3140
  makeBulletinStatusHandler,
3121
3141
  CHUNK_MORTALITY_PERIOD,
@@ -3137,6 +3157,9 @@ export {
3137
3157
  encryptContent,
3138
3158
  __selectStorageProviderModeForTest,
3139
3159
  resolveEffectiveMnemonic,
3160
+ resolveEnvId,
3161
+ shouldPublishManifest,
3162
+ validateNoManifestFlags,
3140
3163
  chooseSignerInput,
3141
3164
  isPhoneSignerActive,
3142
3165
  shouldHandoverName,
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-5FLTDWWP.js";
5
5
  import {
6
6
  DOT_PRODUCT_ID
7
- } from "./chunk-P7MXONT2.js";
7
+ } from "./chunk-L53JPHIS.js";
8
8
  import {
9
9
  DEFAULT_MNEMONIC
10
- } from "./chunk-46BS77ZZ.js";
10
+ } from "./chunk-C65GAMEI.js";
11
11
 
12
12
  // src/deploy-actors.ts
13
13
  var DEFAULT_WORKER_SURI = DEFAULT_MNEMONIC;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-MYQO2UNZ.js";
3
+ } from "./chunk-TU7PXMIV.js";
4
4
 
5
5
  // src/version-check.ts
6
6
  import { execSync, execFileSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  package_default,
3
3
  writeRunState
4
- } from "./chunk-XIMLHQX5.js";
4
+ } from "./chunk-AYDNHTZS.js";
5
5
 
6
6
  // src/memory-report.ts
7
7
  import * as fs2 from "fs";
@@ -134,7 +134,7 @@ function initTelemetry() {
134
134
  if (process.env.BULLETIN_DEPLOY_USE_AMBIENT_SENTRY === "1") {
135
135
  return;
136
136
  }
137
- const dsn = process.env.SENTRY_DSN || (true ? "" : "");
137
+ const dsn = process.env.SENTRY_DSN || (true ? "https://e021c025d79c4c3ade2862a11f13c40b@o4511059872841728.ingest.de.sentry.io/4511093597405264" : "");
138
138
  if (!dsn) return;
139
139
  Sentry.init({
140
140
  dsn,
@@ -334,13 +334,13 @@ function computeDeployOutcome(errorCategory, isSad, sadReason) {
334
334
  return "clean";
335
335
  }
336
336
  var ERROR_KIND_RULES = [
337
- [/Contract reverted|Contract execution would revert|revert(?:ed|ing)?\s*\(flags=[0-9]+\)/i, "contract-revert"],
337
+ [/Contract reverted|Contract execution would revert|revert(?:ed|ing)?\s*\(flags=[0-9]+\)|"type"\s*:\s*"ContractReverted"/i, "contract-revert"],
338
338
  [/timed out after \d+s waiting for block|Transaction not included after \d+s|Transaction did not settle within/i, "chain-timeout"],
339
339
  [/\bstale\b.*nonce|nonce.*\bstale\b|"type"\s*:\s*"(?:Future|Stale)"|Invalid::Future|tx rejected by pool/i, "nonce-stale"],
340
340
  [/heartbeat timeout|WS halt|Unable to connect|ChainHead disjointed|websocket.*closed|socket closed|disconnect/i, "connection"],
341
341
  [/requires ProofOfPersonhood(?:Full|Lite|Light),\s*but this signer is NoStatus/i, "naming.pop_required"],
342
342
  [/requires NoStatus,\s*but this signer is ProofOfPersonhood/i, "naming.nostatus_required"],
343
- [/Cannot decode zero data.*with ABI parameters/i, "naming.contract_unavailable"],
343
+ [/Cannot decode zero data.*with ABI parameters/i, "dotns.abi_decode_empty"],
344
344
  // Issue #1060: contractCall's own empty-`0x`-data guard (src/dotns.ts, #729) throws
345
345
  // an actionable wrapper instead of letting the raw viem message above reach a
346
346
  // caller. Same failure family (a DotNS contract read came back empty) — classify
@@ -368,6 +368,13 @@ function classifyErrorKind(msg) {
368
368
  }
369
369
  return "unknown";
370
370
  }
371
+ function classifyErrorForSpan(msg) {
372
+ return {
373
+ kind: classifyErrorKind(msg),
374
+ message: sanitizeErrorMessage(msg),
375
+ pattern: analyseErrorPattern(msg)
376
+ };
377
+ }
371
378
  function sanitizeErrorMessage(msg) {
372
379
  return scrubPaths(msg.slice(0, 500));
373
380
  }
@@ -398,10 +405,11 @@ async function withSpan(op, description, attributes, fn) {
398
405
  return await fn();
399
406
  } catch (error) {
400
407
  const msg = error.message ?? String(error);
408
+ const { kind, message, pattern } = classifyErrorForSpan(msg);
401
409
  span.setAttribute("error.message", msg);
402
- span.setAttribute("deploy.error_kind", classifyErrorKind(msg));
403
- span.setAttribute("deploy.error_message", sanitizeErrorMessage(msg));
404
- span.setAttribute("deploy.error_pattern_signature", analyseErrorPattern(msg));
410
+ span.setAttribute("deploy.error_kind", kind);
411
+ span.setAttribute("deploy.error_message", message);
412
+ span.setAttribute("deploy.error_pattern_signature", pattern);
405
413
  span.setStatus({ code: 2, message: "internal_error" });
406
414
  throw error;
407
415
  }
@@ -496,12 +504,9 @@ async function withDeploySpan(domain, fn) {
496
504
  } catch (error) {
497
505
  const msg = error.message ?? String(error);
498
506
  span.setAttribute("deploy.status", "error");
499
- span.setAttribute("deploy.error", msg.slice(0, 500));
507
+ setDeployErrorOnSpan(span, msg);
500
508
  const errorCategory = classifyDeployError(msg);
501
509
  span.setAttribute("deploy.error_category", errorCategory);
502
- span.setAttribute("deploy.error_kind", classifyErrorKind(msg));
503
- span.setAttribute("deploy.error_message", sanitizeErrorMessage(msg));
504
- span.setAttribute("deploy.error_pattern_signature", analyseErrorPattern(msg));
505
510
  currentErrorCategory = errorCategory;
506
511
  const isExpected = isExpectedError(msg);
507
512
  span.setAttribute("deploy.expected", isExpected ? "true" : "false");
@@ -578,6 +583,17 @@ function setDeployAttribute(key, value) {
578
583
  if (!deployRootSpan) return;
579
584
  deployRootSpan.setAttribute(key, value);
580
585
  }
586
+ function setDeployErrorOnSpan(span, msg) {
587
+ const { kind, message, pattern } = classifyErrorForSpan(msg);
588
+ span.setAttribute("deploy.error", msg.slice(0, 500));
589
+ span.setAttribute("deploy.error_kind", kind);
590
+ span.setAttribute("deploy.error_message", message);
591
+ span.setAttribute("deploy.error_pattern_signature", pattern);
592
+ }
593
+ function setDeployError(msg) {
594
+ if (!deployRootSpan) return;
595
+ setDeployErrorOnSpan(deployRootSpan, msg);
596
+ }
581
597
  function __setDeployRootSpanForTest(span) {
582
598
  deployRootSpan = span;
583
599
  }
@@ -774,6 +790,7 @@ export {
774
790
  withDeploySpan,
775
791
  setDeployReportContext,
776
792
  setDeployAttribute,
793
+ setDeployError,
777
794
  __setDeployRootSpanForTest,
778
795
  __setSentryForTest,
779
796
  getCurrentSentryTraceId,
@@ -71,12 +71,34 @@ async function fileExists(p) {
71
71
  }
72
72
  }
73
73
  async function importConfig(sourcePath) {
74
- if (sourcePath.endsWith(".ts")) {
75
- const { createJiti } = await import("jiti");
76
- const jiti = createJiti(import.meta.url, { interopDefault: false });
77
- return jiti.import(sourcePath);
74
+ try {
75
+ if (sourcePath.endsWith(".ts")) {
76
+ const { createJiti } = await import("jiti");
77
+ const jiti = createJiti(import.meta.url, { interopDefault: false });
78
+ return await jiti.import(sourcePath);
79
+ }
80
+ return await import(pathToFileURL(sourcePath).href);
81
+ } catch (err) {
82
+ if (err instanceof NonRetryableError) throw err;
83
+ throw new NonRetryableError(formatConfigLoadError(sourcePath, err));
78
84
  }
79
- return import(pathToFileURL(sourcePath).href);
85
+ }
86
+ function formatConfigLoadError(sourcePath, err) {
87
+ const message = err instanceof Error ? err.message : String(err);
88
+ const filename = path.basename(sourcePath);
89
+ const base = `Your ${filename} threw while loading: ${message}. Check its required env vars / inputs.`;
90
+ const envVar = extractMissingEnvVar(message);
91
+ return envVar ? `${base}
92
+ Hint: set the ${envVar} environment variable.` : base;
93
+ }
94
+ function extractMissingEnvVar(message) {
95
+ const required = message.match(/\b([A-Za-z_][A-Za-z0-9_]*)\s+is required\b/);
96
+ if (required) return required[1];
97
+ const missing = message.match(
98
+ /missing env(?:ironment)? var(?:iable)?s?[:\s]+([A-Za-z_][A-Za-z0-9_]*)/i
99
+ );
100
+ if (missing) return missing[1];
101
+ return null;
80
102
  }
81
103
  function pickDefault(mod) {
82
104
  if (mod && typeof mod === "object" && "default" in mod) {
@@ -87,5 +109,6 @@ function pickDefault(mod) {
87
109
 
88
110
  export {
89
111
  loadProductConfig,
90
- tryLoadProductConfig
112
+ tryLoadProductConfig,
113
+ formatConfigLoadError
91
114
  };