bulletin-deploy 0.22.0-rc.1 → 0.22.0-rc.2

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 (53) hide show
  1. package/dist/auth/index.js +4 -4
  2. package/dist/auth/vendor/index.js +5 -5
  3. package/dist/auth-config.js +3 -3
  4. package/dist/bug-report.js +4 -4
  5. package/dist/chain-health.js +3 -3
  6. package/dist/chunk-6DDB5QOM.js +40 -0
  7. package/dist/{chunk-KXYSKT5U.js → chunk-7JM6FJM3.js} +21 -1
  8. package/dist/{chunk-DKTKQS2N.js → chunk-C75KFENW.js} +1 -1
  9. package/dist/{chunk-6RQY4VPG.js → chunk-CFSMENKV.js} +4 -4
  10. package/dist/{chunk-FUU5U5GB.js → chunk-HE6CD5SW.js} +2 -2
  11. package/dist/{chunk-OFR4K7P3.js → chunk-L6TCHNO6.js} +22 -7
  12. package/dist/{chunk-4FAL7DFB.js → chunk-PR52KVWQ.js} +174 -40
  13. package/dist/{chunk-RMO7G7X2.js → chunk-PY4R353E.js} +3 -3
  14. package/dist/{chunk-S2N25SYI.js → chunk-PZA33HNQ.js} +1 -1
  15. package/dist/{chunk-Z6EIQVNP.js → chunk-S24T3JSD.js} +4 -4
  16. package/dist/{chunk-NTJRL6TA.js → chunk-UWTR5Z27.js} +1 -1
  17. package/dist/{chunk-7G475SPF.js → chunk-V2UID6F6.js} +1 -1
  18. package/dist/{chunk-BMUDRQYV.js → chunk-WM4BQ7YJ.js} +94 -4
  19. package/dist/{chunk-LTUECTW2.js → chunk-YQF5Y2HS.js} +272 -121
  20. package/dist/{chunk-KDVHMIKK.js → chunk-ZTXHG3LV.js} +1 -1
  21. package/dist/chunk-probe.js +3 -3
  22. package/dist/commands/login.js +18 -17
  23. package/dist/commands/logout.js +5 -5
  24. package/dist/commands/transfer.js +6 -6
  25. package/dist/commands/whoami.js +3 -3
  26. package/dist/deploy-actors.js +8 -8
  27. package/dist/deploy.d.ts +71 -27
  28. package/dist/deploy.js +28 -17
  29. package/dist/dotns.d.ts +18 -5
  30. package/dist/dotns.js +6 -6
  31. package/dist/e2e-nonce-barrier.d.ts +24 -0
  32. package/dist/e2e-nonce-barrier.js +12 -0
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +42 -33
  35. package/dist/manifest/product-preflight.js +3 -3
  36. package/dist/manifest/publish.js +22 -21
  37. package/dist/memory-report.js +2 -2
  38. package/dist/merkle.js +18 -17
  39. package/dist/personhood/bootstrap.js +9 -9
  40. package/dist/personhood/people-client.js +6 -6
  41. package/dist/pool.d.ts +7 -2
  42. package/dist/pool.js +9 -7
  43. package/dist/run-state.d.ts +22 -2
  44. package/dist/run-state.js +9 -1
  45. package/dist/sss-allowance-cache.js +4 -4
  46. package/dist/storage-signer.js +18 -17
  47. package/dist/telemetry.d.ts +1 -1
  48. package/dist/telemetry.js +2 -2
  49. package/dist/version-check.js +3 -3
  50. package/dist/ws.js +4 -4
  51. package/package.json +1 -1
  52. package/tools/release-retry-wrapper.mjs +27 -4
  53. package/dist/{chunk-EHAL4CJM.js → chunk-DBDOISNQ.js} +3 -3
@@ -8,6 +8,10 @@ import {
8
8
  renderLogoutStatus
9
9
  } from "../chunk-YP3LINCF.js";
10
10
  import "../chunk-NJKXXDDK.js";
11
+ import {
12
+ SignerNotAvailableError,
13
+ resolveSigner
14
+ } from "../chunk-2C6SLLBI.js";
11
15
  import {
12
16
  createAuthClient
13
17
  } from "../chunk-PN5JKONF.js";
@@ -21,10 +25,6 @@ import {
21
25
  import {
22
26
  SESSION_EXPIRED_MESSAGE
23
27
  } from "../chunk-IMCDXJ4G.js";
24
- import {
25
- SignerNotAvailableError,
26
- resolveSigner
27
- } from "../chunk-2C6SLLBI.js";
28
28
  import "../chunk-SH2LG52Z.js";
29
29
  import "../chunk-DNXE3Q5D.js";
30
30
  export {
@@ -1,4 +1,9 @@
1
1
  import "../../chunk-NJKXXDDK.js";
2
+ import {
3
+ SignerNotAvailableError,
4
+ parseDevAccountName,
5
+ resolveSigner
6
+ } from "../../chunk-2C6SLLBI.js";
2
7
  import {
3
8
  createAuthClient
4
9
  } from "../../chunk-PN5JKONF.js";
@@ -16,11 +21,6 @@ import {
16
21
  deriveProductPublicKey,
17
22
  sessionRootPublicKey
18
23
  } from "../../chunk-IMCDXJ4G.js";
19
- import {
20
- SignerNotAvailableError,
21
- parseDevAccountName,
22
- resolveSigner
23
- } from "../../chunk-2C6SLLBI.js";
24
24
  import "../../chunk-SH2LG52Z.js";
25
25
  import "../../chunk-DNXE3Q5D.js";
26
26
  export {
@@ -10,10 +10,10 @@ import {
10
10
  hasPersistedSession,
11
11
  readNetworkSuffix,
12
12
  resolveBulletinEndpoints
13
- } from "./chunk-KDVHMIKK.js";
13
+ } from "./chunk-ZTXHG3LV.js";
14
14
  import "./chunk-3NR3T7US.js";
15
- import "./chunk-KXYSKT5U.js";
16
- import "./chunk-BMUDRQYV.js";
15
+ import "./chunk-7JM6FJM3.js";
16
+ import "./chunk-WM4BQ7YJ.js";
17
17
  import "./chunk-SH2LG52Z.js";
18
18
  import "./chunk-DNXE3Q5D.js";
19
19
  export {
@@ -10,10 +10,10 @@ import {
10
10
  offerBugReport,
11
11
  scrubSecrets,
12
12
  setDeployContext
13
- } from "./chunk-RMO7G7X2.js";
14
- import "./chunk-S2N25SYI.js";
15
- import "./chunk-KXYSKT5U.js";
16
- import "./chunk-BMUDRQYV.js";
13
+ } from "./chunk-PY4R353E.js";
14
+ import "./chunk-PZA33HNQ.js";
15
+ import "./chunk-7JM6FJM3.js";
16
+ import "./chunk-WM4BQ7YJ.js";
17
17
  import "./chunk-SH2LG52Z.js";
18
18
  export {
19
19
  buildCliFlagsSummary,
@@ -3,9 +3,9 @@ import {
3
3
  DEFAULT_WINDOW_BLOCKS,
4
4
  MAX_SPANS_PER_SAMPLER,
5
5
  endpointHost
6
- } from "./chunk-NTJRL6TA.js";
7
- import "./chunk-KXYSKT5U.js";
8
- import "./chunk-BMUDRQYV.js";
6
+ } from "./chunk-UWTR5Z27.js";
7
+ import "./chunk-7JM6FJM3.js";
8
+ import "./chunk-WM4BQ7YJ.js";
9
9
  import "./chunk-SH2LG52Z.js";
10
10
  export {
11
11
  ChainHealthSampler,
@@ -0,0 +1,40 @@
1
+ // src/e2e-nonce-barrier.ts
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ var NONCE_SEED_BARRIER_ENV = "BULLETIN_DEPLOY_E2E_NONCE_SEED_BARRIER";
5
+ async function awaitNonceSeedBarrier(opts) {
6
+ const parties = opts.parties ?? 2;
7
+ const deadline = Date.now() + (opts.timeoutMs ?? 12e4);
8
+ const pollMs = opts.pollMs ?? 200;
9
+ fs.mkdirSync(opts.dir, { recursive: true });
10
+ fs.writeFileSync(path.join(opts.dir, `${opts.id ?? process.pid}.seed`), String(opts.seed));
11
+ const seedFiles = () => fs.readdirSync(opts.dir).filter((f) => f.endsWith(".seed"));
12
+ const readSeeds = (files) => files.map((f) => Number(fs.readFileSync(path.join(opts.dir, f), "utf8"))).sort((a, b) => a - b);
13
+ for (; ; ) {
14
+ const files = seedFiles();
15
+ if (files.length >= parties) return { met: true, seeds: readSeeds(files) };
16
+ if (Date.now() >= deadline) return { met: false, seeds: readSeeds(files) };
17
+ await new Promise((r) => setTimeout(r, pollMs));
18
+ }
19
+ }
20
+ var used = false;
21
+ async function e2eNonceSeedBarrier(seed, env = process.env) {
22
+ const dir = env[NONCE_SEED_BARRIER_ENV];
23
+ if (!dir || used) return;
24
+ used = true;
25
+ const parties = Number(env[`${NONCE_SEED_BARRIER_ENV}_PARTIES`] || 2);
26
+ const timeoutMs = Number(env[`${NONCE_SEED_BARRIER_ENV}_TIMEOUT_MS`] || 12e4);
27
+ console.log(` E2E nonce-seed barrier: seed ${seed}, waiting for ${parties} parties`);
28
+ const r = await awaitNonceSeedBarrier({ dir, seed, parties, timeoutMs });
29
+ console.log(r.met ? ` E2E nonce-seed barrier met: seeds [${r.seeds.join(", ")}]` : ` E2E nonce-seed barrier timed out after ${timeoutMs}ms: seeds [${r.seeds.join(", ")}]`);
30
+ }
31
+ function __resetNonceSeedBarrierForTest() {
32
+ used = false;
33
+ }
34
+
35
+ export {
36
+ NONCE_SEED_BARRIER_ENV,
37
+ awaitNonceSeedBarrier,
38
+ e2eNonceSeedBarrier,
39
+ __resetNonceSeedBarrierForTest
40
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  package_default,
3
3
  writeRunState
4
- } from "./chunk-BMUDRQYV.js";
4
+ } from "./chunk-WM4BQ7YJ.js";
5
5
  import {
6
6
  FALLBACK_CONFIG_ORIGIN,
7
7
  SHIPPED_CONFIG_ORIGIN
@@ -352,6 +352,10 @@ function getDeployAttributes(domain) {
352
352
  "deploy.tool_version": VERSION,
353
353
  "deploy.runner": resolveRunner(),
354
354
  "deploy.runner_type": resolveRunnerType(),
355
+ // #1646: the telemetry verifier scopes its Sentry query to the current CI run
356
+ // with these (strings, present on every span: both-values rule).
357
+ "deploy.ci_run_id": process.env.GITHUB_RUN_ID || "none",
358
+ "deploy.ci_run_attempt": process.env.GITHUB_RUN_ATTEMPT || "none",
355
359
  // Present on every span so a dashboard can compute count_if(deploy.version_status,
356
360
  // "outdated") / count() — see classifyVersionFreshness in version-check.ts.
357
361
  "deploy.version_status": versionFreshness,
@@ -428,6 +432,16 @@ var ERROR_KIND_RULES = [
428
432
  // (2026-08-06 telemetry sweep: this was the largest live `unknown` bucket —
429
433
  // 31 spans, 30 of them env=preview, from the per-env authorizer gap #1209.)
430
434
  [/is not authorized for Bulletin storage/i, "storage.rejected"],
435
+ // The three chunk-inclusion / stuck-queue messages (src/deploy.ts
436
+ // ChunkInclusionUnverifiedError, src/pool.ts stuckQueueMessage). Ahead of the
437
+ // generic infra rules: the unverified message interpolates the probe's failure
438
+ // reason, which routinely reads "timed out" / "websocket closed" and would be
439
+ // claimed by chain-timeout or connection; the stuck-queue message says "every
440
+ // chunk would time out", and both inclusion messages end up before the broader
441
+ // /chunk.*failed after.*retr/ and /not finalised after/ fallbacks.
442
+ [/Could not verify that chunk .+ is stored on-chain/i, "chain.chunk_unverified"],
443
+ [/still absent at the best block after \d+ re-upload rounds/i, "chain.chunk_not_included"],
444
+ [/has a stuck pending-tx queue/i, "chain.queue_stuck"],
431
445
  // Revive surfaces the personhood gate as a bare revert reason rather than the
432
446
  // "requires ProofOfPersonhoodX, but this signer is NoStatus" prose matched
433
447
  // further down — same user-actionable cause, so it shares that kind. Ordered
@@ -620,6 +634,12 @@ var ERROR_KIND_CATEGORY = {
620
634
  "chain.quota_exhausted": "user",
621
635
  "chain.bad_proof": "environment",
622
636
  "chain.chunk_failed": "environment",
637
+ "chain.chunk_unverified": "environment",
638
+ "chain.chunk_not_included": "environment",
639
+ // Always the node's pool state, not the operator's: a pinned index is only the
640
+ // remedy (unset/pick another), the stuck queue is the cause, and the same
641
+ // message is also thrown for a direct signer that pinned nothing.
642
+ "chain.queue_stuck": "environment",
623
643
  "chain.tx_dropped": "environment",
624
644
  "chain.tx_invalid": "environment",
625
645
  "chain.not_finalised": "environment",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  captureWarning
3
- } from "./chunk-KXYSKT5U.js";
3
+ } from "./chunk-7JM6FJM3.js";
4
4
 
5
5
  // src/chunk-probe.ts
6
6
  import { Twox128, Blake2128Concat, decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  verifyEmbeddedAppManifests
3
- } from "./chunk-EHAL4CJM.js";
3
+ } from "./chunk-DBDOISNQ.js";
4
4
  import {
5
5
  pessimisticSizePreflight
6
6
  } from "./chunk-YTRNJMI4.js";
@@ -19,13 +19,13 @@ import {
19
19
  setBulletinEndpoints,
20
20
  storeDirectory,
21
21
  storeFile
22
- } from "./chunk-LTUECTW2.js";
22
+ } from "./chunk-YQF5Y2HS.js";
23
23
  import {
24
24
  DEFAULT_TLD,
25
25
  DotNS,
26
26
  parseDomainName,
27
27
  stripTldSuffix
28
- } from "./chunk-4FAL7DFB.js";
28
+ } from "./chunk-PR52KVWQ.js";
29
29
  import {
30
30
  DEFAULT_ENV_ID,
31
31
  getPopSelfServeConfig,
@@ -36,7 +36,7 @@ import {
36
36
  setDeployAttribute,
37
37
  withManifestSpan,
38
38
  withSpan
39
- } from "./chunk-KXYSKT5U.js";
39
+ } from "./chunk-7JM6FJM3.js";
40
40
  import {
41
41
  NonRetryableError
42
42
  } from "./chunk-SH2LG52Z.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  endpointHost
3
- } from "./chunk-NTJRL6TA.js";
3
+ } from "./chunk-UWTR5Z27.js";
4
4
  import {
5
5
  captureWarning
6
- } from "./chunk-KXYSKT5U.js";
6
+ } from "./chunk-7JM6FJM3.js";
7
7
 
8
8
  // src/ws.ts
9
9
  import { getWsProvider as papiGetWsProvider } from "polkadot-api/ws";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getWsProvider
3
- } from "./chunk-FUU5U5GB.js";
3
+ } from "./chunk-HE6CD5SW.js";
4
4
  import {
5
5
  NonRetryableError
6
6
  } from "./chunk-SH2LG52Z.js";
@@ -132,6 +132,7 @@ var STUCK_NONCE_GAP_THRESHOLD = 8;
132
132
  var NONCE_HEALTH_SAMPLES = 8;
133
133
  var NONCE_HEALTH_TIMEOUT_MS = 1e4;
134
134
  var NONCE_HEALTH_CONFIRM_DELAY_MS = 2 * BULLETIN_BLOCK_TIME_SECS * 1e3;
135
+ var NONCE_HEALTH_CONFIRM_READS = 5;
135
136
  function nonceGapVerdict(onchain, nextIndex, threshold = STUCK_NONCE_GAP_THRESHOLD) {
136
137
  return nextIndex - onchain > threshold ? "stuck" : "healthy";
137
138
  }
@@ -163,15 +164,28 @@ async function checkPoolAccountNonceHealth(address, deps) {
163
164
  const nextIndex = Math.max(...got);
164
165
  const result = { verdict: nonceGapVerdict(onchain, nextIndex, deps.threshold), onchain, nextIndex, gap: nextIndex - onchain, samples: got };
165
166
  if (result.verdict !== "stuck") return result;
167
+ result.backendLocal = nonceGapVerdict(onchain, Math.min(...got), deps.threshold) === "healthy";
168
+ if (!result.backendLocal) {
169
+ return {
170
+ ...result,
171
+ verdict: "unknown",
172
+ reason: `gap ${result.gap} on every nextIndex sample (a gossiped queue): a busy account, not a backend-local stuck queue`
173
+ };
174
+ }
166
175
  const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
167
- await sleep(deps.confirmDelayMs ?? NONCE_HEALTH_CONFIRM_DELAY_MS);
168
- try {
169
- const later = Number(await withTimeout(() => deps.readOnchainNonce(address), timeoutMs, "on-chain nonce re-read"));
176
+ const delayMs = deps.confirmDelayMs ?? NONCE_HEALTH_CONFIRM_DELAY_MS;
177
+ const reads = deps.confirmReads ?? NONCE_HEALTH_CONFIRM_READS;
178
+ for (let i = 0; i < reads; i++) {
179
+ await sleep(delayMs);
180
+ let later;
181
+ try {
182
+ later = Number(await withTimeout(() => deps.readOnchainNonce(address), timeoutMs, "on-chain nonce re-read"));
183
+ } catch (e) {
184
+ return { ...result, verdict: "unknown", reason: `on-chain nonce re-read: ${e?.message ?? e}` };
185
+ }
170
186
  if (later > onchain) return { ...result, verdict: "healthy", onchain: later, gap: nextIndex - later };
171
- return result;
172
- } catch (e) {
173
- return { ...result, verdict: "unknown", reason: `on-chain nonce re-read: ${e?.message ?? e}` };
174
187
  }
188
+ return result;
175
189
  }
176
190
  var StuckPoolAccountError = class extends NonRetryableError {
177
191
  constructor(message, skippedStuck) {
@@ -524,6 +538,7 @@ export {
524
538
  STUCK_NONCE_GAP_THRESHOLD,
525
539
  NONCE_HEALTH_SAMPLES,
526
540
  nonceGapVerdict,
541
+ withTimeout,
527
542
  checkPoolAccountNonceHealth,
528
543
  StuckPoolAccountError,
529
544
  stuckQueueMessage,