bulletin-deploy 0.19.3 → 0.19.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 (69) hide show
  1. package/assets/environments.json +5 -5
  2. package/bin/bulletin-deploy +10 -1
  3. package/dist/auth/index.js +7 -7
  4. package/dist/auth/vendor/index.js +2 -2
  5. package/dist/auth-config.js +5 -5
  6. package/dist/bug-report.js +5 -4
  7. package/dist/chain-health.js +4 -3
  8. package/dist/{chunk-PSYA6E5M.js → chunk-2P4EZOFF.js} +1 -1
  9. package/dist/{chunk-NA3SXVY6.js → chunk-3NR3T7US.js} +22 -12
  10. package/dist/{chunk-6FQJLLEF.js → chunk-6J4WRFRL.js} +1 -1
  11. package/dist/{chunk-LPTKBQII.js → chunk-7DDOVCV5.js} +1 -1
  12. package/dist/{chunk-I5PNPQZO.js → chunk-ANX3RZAS.js} +38 -10
  13. package/dist/{chunk-IP6ABIIC.js → chunk-BFK5UCUJ.js} +29 -4
  14. package/dist/{chunk-H4OZ6PTA.js → chunk-C437RTTU.js} +8 -8
  15. package/dist/{chunk-VBIFKNUS.js → chunk-CCIBF55X.js} +1 -1
  16. package/dist/{chunk-IW3X2MJF.js → chunk-D3YME2EG.js} +30 -1
  17. package/dist/{chunk-6MSHWNJT.js → chunk-D6BE3RAU.js} +138 -54
  18. package/dist/{chunk-3MAIF2SF.js → chunk-F24S4EV5.js} +49 -7
  19. package/dist/{chunk-WPC2PUCV.js → chunk-H44LXDQJ.js} +43 -8
  20. package/dist/{chunk-5FLTDWWP.js → chunk-H44NO63C.js} +1 -1
  21. package/dist/{chunk-3ACNAWUD.js → chunk-JTH3ISLR.js} +3 -3
  22. package/dist/{chunk-NKDGBZBP.js → chunk-O56KLG7Z.js} +2 -2
  23. package/dist/{chunk-KTKFHROI.js → chunk-OONQPYHM.js} +4 -4
  24. package/dist/{chunk-SNFGJOR2.js → chunk-R3BXRRKE.js} +1 -1
  25. package/dist/{chunk-ZOC4GITL.js → chunk-SH2LG52Z.js} +5 -1
  26. package/dist/{chunk-ABMNC34K.js → chunk-U2QO5G35.js} +2 -2
  27. package/dist/{chunk-QU5GJF6U.js → chunk-UFP2XWZ4.js} +3 -3
  28. package/dist/chunk-ZG3HAH5A.js +18 -0
  29. package/dist/{chunk-RJDHC56V.js → chunk-ZZIOS4RG.js} +53 -16
  30. package/dist/chunk-probe.js +4 -3
  31. package/dist/commands/login.js +24 -23
  32. package/dist/commands/logout.js +7 -7
  33. package/dist/commands/transfer.js +7 -6
  34. package/dist/commands/whoami.js +5 -5
  35. package/dist/deploy-actors.js +10 -9
  36. package/dist/deploy.d.ts +45 -18
  37. package/dist/deploy.js +30 -20
  38. package/dist/dotns.d.ts +56 -2
  39. package/dist/dotns.js +9 -6
  40. package/dist/environments.d.ts +7 -1
  41. package/dist/environments.js +2 -2
  42. package/dist/errors.d.ts +5 -1
  43. package/dist/errors.js +7 -3
  44. package/dist/incremental-stats.d.ts +14 -0
  45. package/dist/incremental-stats.js +1 -1
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.js +23 -22
  48. package/dist/manifest/config-load.js +3 -3
  49. package/dist/manifest/publish.d.ts +1 -0
  50. package/dist/manifest/publish.js +23 -22
  51. package/dist/manifest/schema.js +1 -1
  52. package/dist/manifest-embed.js +2 -2
  53. package/dist/manifest-fetch.js +2 -2
  54. package/dist/manifest-roundtrip.js +2 -2
  55. package/dist/manifest.d.ts +14 -1
  56. package/dist/manifest.js +5 -1
  57. package/dist/memory-report.js +3 -2
  58. package/dist/merkle.js +20 -19
  59. package/dist/mnemonic.d.ts +35 -0
  60. package/dist/mnemonic.js +8 -0
  61. package/dist/personhood/bootstrap.js +7 -6
  62. package/dist/personhood/people-client.js +7 -6
  63. package/dist/run-state.js +1 -1
  64. package/dist/sss-allowance-cache.js +6 -6
  65. package/dist/storage-signer.js +20 -19
  66. package/dist/telemetry.d.ts +2 -1
  67. package/dist/telemetry.js +5 -2
  68. package/dist/version-check.js +4 -3
  69. package/package.json +4 -4
@@ -14,7 +14,7 @@
14
14
  "tld": "testnet",
15
15
  "autoAccountMapping": true,
16
16
  "nativeToEthRatio": 100000000,
17
- "registerStorageDeposit": 2000000000000,
17
+ "registerStorageDeposit": 50000000000,
18
18
  "popSelfServe": {
19
19
  "sudoEnvLabel": "Preview",
20
20
  "personhoodFaucetUrl": "https://sudo.personhood.dev/personhood-faucet",
@@ -46,7 +46,7 @@
46
46
  "ipfs": "https://previewnet.substrate.dev",
47
47
  "autoAccountMapping": true,
48
48
  "nativeToEthRatio": 100000000,
49
- "registerStorageDeposit": 2000000000000,
49
+ "registerStorageDeposit": 50000000000,
50
50
  "contracts": {}
51
51
  },
52
52
  {
@@ -82,7 +82,7 @@
82
82
  "tld": "paseo",
83
83
  "autoAccountMapping": true,
84
84
  "nativeToEthRatio": 100000000,
85
- "registerStorageDeposit": 2000000000000,
85
+ "registerStorageDeposit": 50000000000,
86
86
  "popSelfServe": {
87
87
  "sudoEnvLabel": "Next V2",
88
88
  "faucetUrl": "https://faucet.polkadot.io/?parachain=1500",
@@ -117,7 +117,7 @@
117
117
  "tld": "dot",
118
118
  "autoAccountMapping": true,
119
119
  "nativeToEthRatio": 100000000,
120
- "registerStorageDeposit": 2000000000000,
120
+ "registerStorageDeposit": 50000000000,
121
121
  "contracts": {
122
122
  "DOTNS_PROTOCOL_REGISTRY": "0xD19e3D0C97CF501125a04A97405e3e6592fa846E",
123
123
  "DOTNS_REGISTRAR": "0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab",
@@ -146,7 +146,7 @@
146
146
  "webGateway": "dev-dot.li",
147
147
  "autoAccountMapping": true,
148
148
  "nativeToEthRatio": 100000000,
149
- "registerStorageDeposit": 2000000000000,
149
+ "registerStorageDeposit": 50000000000,
150
150
  "contracts": {
151
151
  "DOTNS_PROTOCOL_REGISTRY": "0xEdb3e17649ABccc69e6fab4cc640bc578C47AbeA",
152
152
  "DOTNS_REGISTRAR": "0x7f0dF075cc8B7FE7218E90fFC5a553450dB120F3",
@@ -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, resolveEffectiveMnemonic, resolveEnvId, shouldPublishManifest, nonInteractivePhoneConfirmationError } from "../dist/deploy.js";
9
+ import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY, isConnectionError, isBenignTeardownError, resolveEffectiveMnemonic, mnemonicConflictNotice, resolveEnvId, shouldPublishManifest, nonInteractivePhoneConfirmationError } from "../dist/deploy.js";
10
10
  import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStateActive, markRelaunchOomHintShown, setVersionFreshness } from "../dist/telemetry.js";
11
11
  import { handleFailedDeploy, handlePreflightVersionCheck, fetchVersionInfo, preReleaseWarning, checkNodeVersion, classifyVersionFreshness, isInteractive } from "../dist/version-check.js";
12
12
  import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
@@ -82,6 +82,15 @@ const effectiveMnemonic = resolveEffectiveMnemonic({
82
82
  envDotnsMnemonic: process.env.DOTNS_MNEMONIC,
83
83
  });
84
84
 
85
+ // #1461: surface it when MNEMONIC and DOTNS_MNEMONIC are both set and
86
+ // disagree — only meaningful when no --mnemonic flag was given (a flag makes
87
+ // both env vars irrelevant), and skipped on --help/--version since neither
88
+ // deploys anything.
89
+ if (!flags.mnemonic && !flags.help && !flags.version) {
90
+ const mnemonicNotice = mnemonicConflictNotice({ envMnemonic: process.env.MNEMONIC, envDotnsMnemonic: process.env.DOTNS_MNEMONIC });
91
+ if (mnemonicNotice) console.error(mnemonicNotice);
92
+ }
93
+
85
94
  // #1165: the env id actually targeted this session — --env flag >
86
95
  // BULLETIN_DEPLOY_ENV env var. `undefined` here still means "let
87
96
  // deploy()/the DEFAULT_ENV_ID fallback below decide" — this only resolves
@@ -1,4 +1,9 @@
1
1
  import "../chunk-JQKKMUCT.js";
2
+ import {
3
+ renderLoginStatus,
4
+ renderLogoutStatus,
5
+ renderQrCode
6
+ } from "../chunk-RIRDBSBG.js";
2
7
  import {
3
8
  BULLETIN_RESOURCE,
4
9
  DEFAULT_RESOURCES,
@@ -8,14 +13,9 @@ import {
8
13
  requestResourceAllocation,
9
14
  resolveSigner,
10
15
  summarizeOutcomes
11
- } from "../chunk-5FLTDWWP.js";
12
- import {
13
- renderLoginStatus,
14
- renderLogoutStatus,
15
- renderQrCode
16
- } from "../chunk-RIRDBSBG.js";
16
+ } from "../chunk-H44NO63C.js";
17
17
  import "../chunk-TSPERKUS.js";
18
- import "../chunk-ZOC4GITL.js";
18
+ import "../chunk-SH2LG52Z.js";
19
19
  export {
20
20
  BULLETIN_RESOURCE,
21
21
  DEFAULT_RESOURCES,
@@ -12,9 +12,9 @@ import {
12
12
  resolveSigner,
13
13
  sessionRootPublicKey,
14
14
  summarizeOutcomes
15
- } from "../../chunk-5FLTDWWP.js";
15
+ } from "../../chunk-H44NO63C.js";
16
16
  import "../../chunk-TSPERKUS.js";
17
- import "../../chunk-ZOC4GITL.js";
17
+ import "../../chunk-SH2LG52Z.js";
18
18
  export {
19
19
  BULLETIN_RESOURCE,
20
20
  DEFAULT_RESOURCES,
@@ -9,12 +9,12 @@ import {
9
9
  getPeopleChainEndpoints,
10
10
  hasPersistedSession,
11
11
  resolveBulletinEndpoints
12
- } from "./chunk-ABMNC34K.js";
12
+ } from "./chunk-U2QO5G35.js";
13
13
  import "./chunk-TSPERKUS.js";
14
- import "./chunk-NA3SXVY6.js";
15
- import "./chunk-ZOC4GITL.js";
16
- import "./chunk-IP6ABIIC.js";
17
- import "./chunk-KTKFHROI.js";
14
+ import "./chunk-3NR3T7US.js";
15
+ import "./chunk-BFK5UCUJ.js";
16
+ import "./chunk-OONQPYHM.js";
17
+ import "./chunk-SH2LG52Z.js";
18
18
  export {
19
19
  DOT_DAPP_ID,
20
20
  DOT_DERIVATION_INDEX,
@@ -10,10 +10,11 @@ import {
10
10
  offerBugReport,
11
11
  scrubSecrets,
12
12
  setDeployContext
13
- } from "./chunk-QU5GJF6U.js";
14
- import "./chunk-SNFGJOR2.js";
15
- import "./chunk-IP6ABIIC.js";
16
- import "./chunk-KTKFHROI.js";
13
+ } from "./chunk-UFP2XWZ4.js";
14
+ import "./chunk-R3BXRRKE.js";
15
+ import "./chunk-BFK5UCUJ.js";
16
+ import "./chunk-OONQPYHM.js";
17
+ import "./chunk-SH2LG52Z.js";
17
18
  export {
18
19
  buildCliFlagsSummary,
19
20
  buildLabels,
@@ -3,9 +3,10 @@ import {
3
3
  DEFAULT_WINDOW_BLOCKS,
4
4
  MAX_SPANS_PER_SAMPLER,
5
5
  endpointHost
6
- } from "./chunk-VBIFKNUS.js";
7
- import "./chunk-IP6ABIIC.js";
8
- import "./chunk-KTKFHROI.js";
6
+ } from "./chunk-CCIBF55X.js";
7
+ import "./chunk-BFK5UCUJ.js";
8
+ import "./chunk-OONQPYHM.js";
9
+ import "./chunk-SH2LG52Z.js";
9
10
  export {
10
11
  ChainHealthSampler,
11
12
  DEFAULT_WINDOW_BLOCKS,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  captureWarning
3
- } from "./chunk-IP6ABIIC.js";
3
+ } from "./chunk-BFK5UCUJ.js";
4
4
 
5
5
  // src/chunk-probe.ts
6
6
  import { Twox128, Blake2128Concat, decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
@@ -1,6 +1,8 @@
1
1
  import {
2
- NonRetryableError
3
- } from "./chunk-ZOC4GITL.js";
2
+ FALLBACK_CONFIG_ORIGIN,
3
+ NonRetryableError,
4
+ SHIPPED_CONFIG_ORIGIN
5
+ } from "./chunk-SH2LG52Z.js";
4
6
 
5
7
  // src/environments.ts
6
8
  import * as fs from "fs/promises";
@@ -23,7 +25,7 @@ var environments_default = {
23
25
  tld: "testnet",
24
26
  autoAccountMapping: true,
25
27
  nativeToEthRatio: 1e8,
26
- registerStorageDeposit: 2e12,
28
+ registerStorageDeposit: 5e10,
27
29
  popSelfServe: {
28
30
  sudoEnvLabel: "Preview",
29
31
  personhoodFaucetUrl: "https://sudo.personhood.dev/personhood-faucet",
@@ -55,7 +57,7 @@ var environments_default = {
55
57
  ipfs: "https://previewnet.substrate.dev",
56
58
  autoAccountMapping: true,
57
59
  nativeToEthRatio: 1e8,
58
- registerStorageDeposit: 2e12,
60
+ registerStorageDeposit: 5e10,
59
61
  contracts: {}
60
62
  },
61
63
  {
@@ -91,7 +93,7 @@ var environments_default = {
91
93
  tld: "paseo",
92
94
  autoAccountMapping: true,
93
95
  nativeToEthRatio: 1e8,
94
- registerStorageDeposit: 2e12,
96
+ registerStorageDeposit: 5e10,
95
97
  popSelfServe: {
96
98
  sudoEnvLabel: "Next V2",
97
99
  faucetUrl: "https://faucet.polkadot.io/?parachain=1500",
@@ -126,7 +128,7 @@ var environments_default = {
126
128
  tld: "dot",
127
129
  autoAccountMapping: true,
128
130
  nativeToEthRatio: 1e8,
129
- registerStorageDeposit: 2e12,
131
+ registerStorageDeposit: 5e10,
130
132
  contracts: {
131
133
  DOTNS_PROTOCOL_REGISTRY: "0xD19e3D0C97CF501125a04A97405e3e6592fa846E",
132
134
  DOTNS_REGISTRAR: "0x4f06E818Ba3d987704fd91cf3d868E4b019106Ab",
@@ -155,7 +157,7 @@ var environments_default = {
155
157
  webGateway: "dev-dot.li",
156
158
  autoAccountMapping: true,
157
159
  nativeToEthRatio: 1e8,
158
- registerStorageDeposit: 2e12,
160
+ registerStorageDeposit: 5e10,
159
161
  contracts: {
160
162
  DOTNS_PROTOCOL_REGISTRY: "0xEdb3e17649ABccc69e6fab4cc640bc578C47AbeA",
161
163
  DOTNS_REGISTRAR: "0x7f0dF075cc8B7FE7218E90fFC5a553450dB120F3",
@@ -519,11 +521,15 @@ function validateContractAddresses(contracts, envId, sources) {
519
521
  }
520
522
  }
521
523
  }
522
- function describeContractSources(envContracts, cliContracts, source, userFilePath, envId) {
524
+ function describeContractSources(envContracts, cliContracts, source, userFilePath, envId, userFileKeys) {
523
525
  const env = envId ?? "unknown";
524
- const docOrigin = source === "file" && userFilePath ? `${userFilePath} (environment ${env})` : source === "hardcoded-fallback" ? `the built-in fallback for ${env}` : `assets/environments.json shipped with bulletin-deploy (environment ${env})`;
526
+ const shippedOrigin = source === "hardcoded-fallback" ? `${FALLBACK_CONFIG_ORIGIN} ${env}` : `${SHIPPED_CONFIG_ORIGIN} (environment ${env})`;
527
+ const fileOrigin = userFilePath ? `${userFilePath} (environment ${env})` : null;
528
+ const declared = new Set(userFileKeys ?? []);
525
529
  const out = {};
526
- for (const key of Object.keys(envContracts)) out[key] = docOrigin;
530
+ for (const key of Object.keys(envContracts)) {
531
+ out[key] = fileOrigin && declared.has(key) ? fileOrigin : shippedOrigin;
532
+ }
527
533
  for (const [key, addr] of Object.entries(cliContracts ?? {})) out[key] = `the --contract flag or contracts option (${key}=${addr})`;
528
534
  return out;
529
535
  }
@@ -597,19 +603,23 @@ async function loadEnvironments(opts = {}) {
597
603
  const baseDoc = base ?? (isValidDoc(environments_default) ? environments_default : HARDCODED_FALLBACK);
598
604
  const partial = userDoc && typeof userDoc === "object" && !Array.isArray(userDoc) ? userDoc : {};
599
605
  const merged = deepMergeEnvironments(baseDoc, partial);
606
+ const userFileContractKeys = /* @__PURE__ */ Object.create(null);
607
+ for (const e of partial.environments ?? []) {
608
+ if (e?.id && !(e.id in userFileContractKeys)) userFileContractKeys[e.id] = Object.keys(e.contracts ?? {});
609
+ }
600
610
  warn(
601
611
  `bulletin-deploy: Using user-supplied environment file "${userFilePath}" \u2014 values are NOT validated against chain; you own correctness.`
602
612
  );
603
613
  for (const env of merged.environments) {
604
614
  if (env.contracts && Object.keys(env.contracts).length > 0) {
605
615
  try {
606
- validateContractAddresses(env.contracts, env.id, describeContractSources(env.contracts, void 0, "file", userFilePath, env.id));
616
+ validateContractAddresses(env.contracts, env.id, describeContractSources(env.contracts, void 0, "file", userFilePath, env.id, userFileContractKeys[env.id] ?? []));
607
617
  } catch (err) {
608
618
  warn(`bulletin-deploy: Warning: ${err?.message ?? err}`);
609
619
  }
610
620
  }
611
621
  }
612
- return { doc: merged, source: "file", userFilePath };
622
+ return { doc: merged, source: "file", userFilePath, userFileContractKeys };
613
623
  }
614
624
  const bundled = await readBundled(bundledPath, capture);
615
625
  if (bundled) return { doc: bundled, source: "bundled" };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-GRPLHUYC.js";
4
4
  import {
5
5
  DOT_DAPP_ID
6
- } from "./chunk-ABMNC34K.js";
6
+ } from "./chunk-U2QO5G35.js";
7
7
 
8
8
  // src/sss-allowance-cache.ts
9
9
  import { mkdir, readFile, writeFile, unlink } from "fs/promises";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MANIFEST_DIR,
3
3
  MANIFEST_PATH
4
- } from "./chunk-WPC2PUCV.js";
4
+ } from "./chunk-H44LXDQJ.js";
5
5
 
6
6
  // src/manifest-embed.ts
7
7
  import * as fs from "fs";
@@ -16,12 +16,31 @@ var LABEL = String.raw`(?!-)[a-z0-9-]{1,63}(?<!-)`;
16
16
  var TLD_FRAGMENT = "[a-z]{2,63}";
17
17
  var DOMAIN_RE = new RegExp(`^${LABEL}(\\.${LABEL})*\\.${TLD_FRAGMENT}$`, "i");
18
18
  var PRODUCT_LABEL_RE = new RegExp(`^${LABEL}$`);
19
+ var PRODUCT_CONFIG_TOP_LEVEL_FIELDS = [
20
+ "domain",
21
+ "displayName",
22
+ "description",
23
+ "icon",
24
+ "executables",
25
+ "trustedProducts"
26
+ ];
19
27
  function isPlainObject(value) {
20
28
  return typeof value === "object" && value !== null && !Array.isArray(value);
21
29
  }
22
30
  function isNonEmptyString(value) {
23
31
  return typeof value === "string" && value.length > 0;
24
32
  }
33
+ function validateIconFormat(format, label, strict) {
34
+ if (!isNonEmptyString(format)) {
35
+ return [`${label} icon.format must be a non-empty string (got ${JSON.stringify(format)})`];
36
+ }
37
+ if (strict && !ICON_FORMATS.includes(format)) {
38
+ return [
39
+ `${label} icon.format must be one of ${ICON_FORMATS.join(", ")} (got ${JSON.stringify(format)})`
40
+ ];
41
+ }
42
+ return [];
43
+ }
25
44
  function validateTrustedProducts(value, label, strict) {
26
45
  if (!isPlainObject(value))
27
46
  return [`${label} trustedProducts must be an object`];
@@ -329,11 +348,14 @@ function validateRootManifest(input) {
329
348
  } else {
330
349
  if (!isNonEmptyString(input.icon.cid))
331
350
  errors.push("root manifest icon.cid must be a non-empty string");
332
- if (!ICON_FORMATS.includes(input.icon.format)) {
333
- errors.push(
334
- `root manifest icon.format must be one of ${ICON_FORMATS.join(", ")} (got ${JSON.stringify(input.icon.format)})`
335
- );
336
- }
351
+ errors.push(
352
+ ...validateIconFormat(
353
+ input.icon.format,
354
+ "root manifest",
355
+ /* strict */
356
+ false
357
+ )
358
+ );
337
359
  }
338
360
  if (input.trustedProducts !== void 0) {
339
361
  errors.push(
@@ -394,6 +416,9 @@ function validateProductConfig(input) {
394
416
  ]
395
417
  };
396
418
  }
419
+ errors.push(
420
+ ...rejectUnknownFields(input, PRODUCT_CONFIG_TOP_LEVEL_FIELDS, "product config ")
421
+ );
397
422
  if (!isNonEmptyString(input.domain) || !DOMAIN_RE.test(input.domain)) {
398
423
  errors.push(
399
424
  "product config domain must be a non-empty dotNS name ending in a TLD of 2 or more letters (e.g. 'myapp.dot')"
@@ -408,11 +433,14 @@ function validateProductConfig(input) {
408
433
  } else {
409
434
  if (!isNonEmptyString(input.icon.path))
410
435
  errors.push("product config icon.path must be a non-empty string");
411
- if (!ICON_FORMATS.includes(input.icon.format)) {
412
- errors.push(
413
- `product config icon.format must be one of ${ICON_FORMATS.join(", ")}`
414
- );
415
- }
436
+ errors.push(
437
+ ...validateIconFormat(
438
+ input.icon.format,
439
+ "product config",
440
+ /* strict */
441
+ true
442
+ )
443
+ );
416
444
  }
417
445
  if (input.trustedProducts !== void 0) {
418
446
  errors.push(
@@ -1,7 +1,11 @@
1
1
  import {
2
2
  package_default,
3
3
  writeRunState
4
- } from "./chunk-KTKFHROI.js";
4
+ } from "./chunk-OONQPYHM.js";
5
+ import {
6
+ FALLBACK_CONFIG_ORIGIN,
7
+ SHIPPED_CONFIG_ORIGIN
8
+ } from "./chunk-SH2LG52Z.js";
5
9
 
6
10
  // src/memory-report.ts
7
11
  import * as fs2 from "fs";
@@ -284,6 +288,9 @@ var DEPLOY_SEED_P2P = {
284
288
  "deploy.p2p.check_ms": "0",
285
289
  "deploy.p2p.error_variant": "none"
286
290
  };
291
+ function isE2eFixtureTag(tag) {
292
+ return /^e2e-/i.test(tag ?? "");
293
+ }
287
294
  function getDeployAttributes(domain) {
288
295
  const hostApp = process.env.BULLETIN_DEPLOY_HOST_APP;
289
296
  const attrs = {
@@ -308,7 +315,11 @@ function getDeployAttributes(domain) {
308
315
  "deploy.runner_type": resolveRunnerType(),
309
316
  // Present on every span so a dashboard can compute count_if(deploy.version_status,
310
317
  // "outdated") / count() — see classifyVersionFreshness in version-check.ts.
311
- "deploy.version_status": versionFreshness
318
+ "deploy.version_status": versionFreshness,
319
+ // #1539: unconditional (both-values rule) so count_if(deploy.is_e2e_fixture,
320
+ // "true") / "false" both work — see isE2eFixtureTag above for the full
321
+ // rationale, and setDeployAttribute below for the options.tag/--tag path.
322
+ "deploy.is_e2e_fixture": String(isE2eFixtureTag(process.env.DEPLOY_TAG))
312
323
  };
313
324
  if (hostApp) attrs["deploy.host_app"] = hostApp;
314
325
  const hostAppVersion = process.env.BULLETIN_DEPLOY_HOST_APP_VERSION;
@@ -326,16 +337,26 @@ var INVALID_TRANSACTION_VARIANT_CATEGORY = {
326
337
  function structuralCategoryOf(variant) {
327
338
  return variant ? INVALID_TRANSACTION_VARIANT_CATEGORY[variant] : void 0;
328
339
  }
340
+ var CONTRACT_ADDRESS_FAILURE = /no contract deployed at|invalid contract address for|contract call returned empty data/i;
341
+ function cameFromOurConfig(msg) {
342
+ const lower = msg.toLowerCase();
343
+ return lower.includes(`came from ${SHIPPED_CONFIG_ORIGIN.toLowerCase()}`) || lower.includes(`came from ${FALLBACK_CONFIG_ORIGIN.toLowerCase()}`);
344
+ }
345
+ var GENERIC_USER_ERROR = new RegExp(`personhood|owned by|owner mismatch|reserved for original|invalid domain label|not authorized for bulletin|insufficient balance|insufficient funds|quota exhausted|insufficient .* authorization|bip39 mnemonic|ipfs cli not installed|base name is \\d+ chars|cannot register it|NameNotAvailable|name must be lowercase|${PHONE_NONINTERACTIVE_FRAGMENT}`, "i");
329
346
  function isExpectedError(msg, variant) {
330
347
  const structuralCategory = structuralCategoryOf(variant);
331
348
  if (structuralCategory) return structuralCategory === "user";
332
- return new RegExp(`personhood|owned by|owner mismatch|reserved for original|invalid domain label|not authorized for bulletin|insufficient balance|insufficient funds|quota exhausted|insufficient .* authorization|bip39 mnemonic|ipfs cli not installed|base name is \\d+ chars|cannot register it|NameNotAvailable|name must be lowercase|${PHONE_NONINTERACTIVE_FRAGMENT}`, "i").test(msg);
349
+ if (GENERIC_USER_ERROR.test(msg)) return true;
350
+ if (CONTRACT_ADDRESS_FAILURE.test(msg)) {
351
+ return /this address came from/i.test(msg) && !cameFromOurConfig(msg);
352
+ }
353
+ return false;
333
354
  }
334
355
  function classifyDeployError(msg, variant) {
335
356
  const structuralCategory = structuralCategoryOf(variant);
336
357
  if (structuralCategory) return structuralCategory;
337
358
  if (isExpectedError(msg)) return "user";
338
- if (/chunk.*failed after.*retr|tx dropped from best chain|timed out after \d+s waiting for block|Contract reverted|Contract execution would revert|dotns register failed|All promises were rejected|"type"\s*:\s*"Invalid"|Commitment still too new|not finalised after \d+s|chain may have (dropped|evicted)|ReviveApi.*timed out|ReviveApi.*returned empty result|\b(?:commit|register|setSubnodeOwner|setResolver|setContenthash|setText|Revive\.call|Utility\.batch_all) timed out after \d+ms|transaction watcher silent for/i.test(msg)) return "environment";
359
+ if (/chunk.*failed after.*retr|tx dropped from best chain|timed out after \d+s waiting for block|Contract reverted|Contract execution would revert|dotns register failed|All promises were rejected|"type"\s*:\s*"Invalid"|Commitment still too new|not finalised after \d+s|chain may have (dropped|evicted)|ReviveApi.*timed out|ReviveApi.*returned empty result|\b(?:commit|register|setSubnodeOwner|setResolver|setContenthash|setText|Revive\.call|Utility\.batch_all) timed out after \d+ms|transaction watcher silent for|could not determine the DotNS ABI profile/i.test(msg)) return "environment";
339
360
  if (/javascript heap out of memory|allocation failed.*heap|External signer mode is not supported with dotns-cli/i.test(msg)) return "internal";
340
361
  return "unknown";
341
362
  }
@@ -764,6 +785,9 @@ function setDeployReportContext(patch) {
764
785
  function setDeployAttribute(key, value) {
765
786
  if (!deployRootSpan) return;
766
787
  deployRootSpan.setAttribute(key, value);
788
+ if (key === "deploy.tag" && typeof value === "string") {
789
+ deployRootSpan.setAttribute("deploy.is_e2e_fixture", String(isE2eFixtureTag(value)));
790
+ }
767
791
  }
768
792
  function setDeployErrorOnSpan(span, msg, variant) {
769
793
  const { kind, message, pattern } = classifyErrorForSpan(msg, variant);
@@ -976,6 +1000,7 @@ export {
976
1000
  resolveRepo,
977
1001
  resolveRunner,
978
1002
  resolveRunnerType,
1003
+ isE2eFixtureTag,
979
1004
  getDeployAttributes,
980
1005
  isExpectedError,
981
1006
  classifyDeployError,
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-DMNLTQGA.js";
9
9
  import {
10
10
  tryLoadProductConfig
11
- } from "./chunk-NKDGBZBP.js";
11
+ } from "./chunk-O56KLG7Z.js";
12
12
  import {
13
13
  BLAKE2B_256_MULTIHASH_CODE,
14
14
  encodeContenthash,
@@ -20,27 +20,27 @@ import {
20
20
  setBulletinEndpoints,
21
21
  storeDirectory,
22
22
  storeFile
23
- } from "./chunk-6MSHWNJT.js";
23
+ } from "./chunk-D6BE3RAU.js";
24
24
  import {
25
25
  DEFAULT_TLD,
26
26
  DotNS,
27
27
  TX_KIND_SKIPPED,
28
28
  stripTldSuffix
29
- } from "./chunk-RJDHC56V.js";
29
+ } from "./chunk-ZZIOS4RG.js";
30
30
  import {
31
31
  DEFAULT_ENV_ID,
32
32
  getPopSelfServeConfig,
33
33
  loadEnvironments,
34
34
  resolveEndpoints
35
- } from "./chunk-NA3SXVY6.js";
36
- import {
37
- NonRetryableError
38
- } from "./chunk-ZOC4GITL.js";
35
+ } from "./chunk-3NR3T7US.js";
39
36
  import {
40
37
  setDeployAttribute,
41
38
  withManifestSpan,
42
39
  withSpan
43
- } from "./chunk-IP6ABIIC.js";
40
+ } from "./chunk-BFK5UCUJ.js";
41
+ import {
42
+ NonRetryableError
43
+ } from "./chunk-SH2LG52Z.js";
44
44
 
45
45
  // src/manifest/publish.ts
46
46
  import * as fs2 from "fs/promises";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  emitIntervalSpan,
3
3
  setDeployAttribute
4
- } from "./chunk-IP6ABIIC.js";
4
+ } from "./chunk-BFK5UCUJ.js";
5
5
 
6
6
  // src/chain-health.ts
7
7
  var DEFAULT_WINDOW_BLOCKS = 10;
@@ -16,6 +16,13 @@ function computeStats(input) {
16
16
  filesTotal: input.filesTotal,
17
17
  filesStable: input.filesStable,
18
18
  filesVolatile: input.filesVolatile,
19
+ filesStablePacked: input.filesStablePacked ?? input.filesStable,
20
+ heuristicAgreeStable: input.heuristicAgreeStable ?? 0,
21
+ heuristicAgreeVolatile: input.heuristicAgreeVolatile ?? 0,
22
+ heuristicFalseVolatile: input.heuristicFalseVolatile ?? 0,
23
+ heuristicFalseStable: input.heuristicFalseStable ?? 0,
24
+ buildMarkers: input.buildMarkers ?? [],
25
+ unhashedStableSample: input.unhashedStableSample ?? [],
19
26
  probedTotal: input.probeResults.length,
20
27
  probePresent: present.length,
21
28
  probeAbsent: input.probeResults.filter((r) => r.present === false).length,
@@ -43,7 +50,7 @@ function computeStats(input) {
43
50
  };
44
51
  }
45
52
  function telemetryAttributes(s) {
46
- const hitRate = s.filesTotal === 0 ? 0 : s.filesStable / s.filesTotal;
53
+ const hitRate = s.filesTotal === 0 ? 0 : s.filesStablePacked / s.filesTotal;
47
54
  return {
48
55
  "deploy.cache.manifest_source": s.manifestSource,
49
56
  "deploy.cache.manifest_fetch_attempts": String(s.manifestFetchAttempts),
@@ -54,6 +61,28 @@ function telemetryAttributes(s) {
54
61
  "deploy.cache.files_total": String(s.filesTotal),
55
62
  "deploy.cache.files_stable": String(s.filesStable),
56
63
  "deploy.cache.files_volatile": String(s.filesVolatile),
64
+ // Raw per-deploy counts, not ratios — @sentry/node user-defined attributes
65
+ // are string-typed in EAP regardless of value type, so sum()/avg() don't
66
+ // work on them; the arithmetic happens locally on rows pulled from
67
+ // Sentry. A pre-divided ratio would also lose the byte weighting #1539
68
+ // establishes as the correct ranking (see the design doc's "Emission
69
+ // caveat" section).
70
+ "deploy.cache.heuristic_agree_stable": String(s.heuristicAgreeStable),
71
+ "deploy.cache.heuristic_agree_volatile": String(s.heuristicAgreeVolatile),
72
+ "deploy.cache.heuristic_false_volatile": String(s.heuristicFalseVolatile),
73
+ "deploy.cache.heuristic_false_stable": String(s.heuristicFalseStable),
74
+ // Every marker observed in the deployed tree, even when detectFramework
75
+ // returned null (ambiguous or none) — an UNKNOWN deploy still names what
76
+ // it shipped. Comma-joined, "" when no marker matched.
77
+ "deploy.cache.build_markers": s.buildMarkers.join(","),
78
+ // The basename evidence behind heuristic_false_volatile — those are the
79
+ // files a new framework rule could have saved, and this says which ones.
80
+ // There is deliberately no separate count attribute: it would emit
81
+ // heuristic_false_volatile's number under a second name, and a schema
82
+ // where two keys always carry the same value teaches every dashboard
83
+ // author to check whether they really do. Deduped, capped sample,
84
+ // basenames only — a path leaks site structure.
85
+ "deploy.cache.unhashed_stable_sample": s.unhashedStableSample.join(","),
57
86
  "deploy.cache.probed_total": String(s.probedTotal),
58
87
  "deploy.cache.probe_present": String(s.probePresent),
59
88
  "deploy.cache.probe_absent": String(s.probeAbsent),