@parity/product-deploy 0.7.28-rc.0

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 (109) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +233 -0
  3. package/assets/environments.json +313 -0
  4. package/bin/bulletin-bootstrap +84 -0
  5. package/bin/bulletin-deploy +429 -0
  6. package/dist/bug-report.d.ts +29 -0
  7. package/dist/bug-report.js +27 -0
  8. package/dist/chunk-2VAUMZB2.js +284 -0
  9. package/dist/chunk-43HLT335.js +232 -0
  10. package/dist/chunk-5VZQ2KSU.js +231 -0
  11. package/dist/chunk-ADNBLFDP.js +225 -0
  12. package/dist/chunk-BMAEWZYV.js +24 -0
  13. package/dist/chunk-C2TS5MER.js +64 -0
  14. package/dist/chunk-DNXH4QTI.js +2336 -0
  15. package/dist/chunk-FZWJV5AD.js +231 -0
  16. package/dist/chunk-GZD2UFLR.js +8 -0
  17. package/dist/chunk-HOTQDYHD.js +219 -0
  18. package/dist/chunk-IDYGYIMH.js +207 -0
  19. package/dist/chunk-KHVTYIIX.js +146 -0
  20. package/dist/chunk-KJH2T5TQ.js +172 -0
  21. package/dist/chunk-KOSF5FDO.js +49 -0
  22. package/dist/chunk-LZJMVPYW.js +156 -0
  23. package/dist/chunk-MFTODIIT.js +725 -0
  24. package/dist/chunk-MMAZFJDG.js +91 -0
  25. package/dist/chunk-NF2FL4ZO.js +164 -0
  26. package/dist/chunk-OITUIM2E.js +524 -0
  27. package/dist/chunk-P6CHOMN3.js +2368 -0
  28. package/dist/chunk-QMYW3D6E.js +316 -0
  29. package/dist/chunk-QTZNULSH.js +185 -0
  30. package/dist/chunk-RI3ZLNPN.js +71 -0
  31. package/dist/chunk-S7EM5VMW.js +108 -0
  32. package/dist/chunk-T7EEVWNU.js +32 -0
  33. package/dist/chunk-UPWEOGLQ.js +37 -0
  34. package/dist/chunk-ZOC4GITL.js +13 -0
  35. package/dist/chunk-ZYVGHDMU.js +117 -0
  36. package/dist/chunk-probe.d.ts +37 -0
  37. package/dist/chunk-probe.js +18 -0
  38. package/dist/chunker.d.ts +8 -0
  39. package/dist/chunker.js +10 -0
  40. package/dist/deploy.d.ts +299 -0
  41. package/dist/deploy.js +96 -0
  42. package/dist/dotns.d.ts +506 -0
  43. package/dist/dotns.js +101 -0
  44. package/dist/environments.d.ts +104 -0
  45. package/dist/environments.js +23 -0
  46. package/dist/errors.d.ts +6 -0
  47. package/dist/errors.js +8 -0
  48. package/dist/gh-pages-mirror.d.ts +76 -0
  49. package/dist/gh-pages-mirror.js +30 -0
  50. package/dist/incremental-stats.d.ts +69 -0
  51. package/dist/incremental-stats.js +10 -0
  52. package/dist/index.d.ts +23 -0
  53. package/dist/index.js +146 -0
  54. package/dist/manifest/byte-budget.d.ts +46 -0
  55. package/dist/manifest/byte-budget.js +14 -0
  56. package/dist/manifest/config-load.d.ts +36 -0
  57. package/dist/manifest/config-load.js +10 -0
  58. package/dist/manifest/publish.d.ts +54 -0
  59. package/dist/manifest/publish.js +23 -0
  60. package/dist/manifest/schema.d.ts +29 -0
  61. package/dist/manifest/schema.js +10 -0
  62. package/dist/manifest/types.d.ts +90 -0
  63. package/dist/manifest/types.js +6 -0
  64. package/dist/manifest-embed.d.ts +18 -0
  65. package/dist/manifest-embed.js +9 -0
  66. package/dist/manifest-fetch.d.ts +32 -0
  67. package/dist/manifest-fetch.js +21 -0
  68. package/dist/manifest-roundtrip.d.ts +15 -0
  69. package/dist/manifest-roundtrip.js +55 -0
  70. package/dist/manifest.d.ts +44 -0
  71. package/dist/manifest.js +20 -0
  72. package/dist/memory-report.d.ts +95 -0
  73. package/dist/memory-report.js +17 -0
  74. package/dist/merkle.d.ts +50 -0
  75. package/dist/merkle.js +33 -0
  76. package/dist/personhood/bind-paid-alias.d.ts +43 -0
  77. package/dist/personhood/bind-paid-alias.js +10 -0
  78. package/dist/personhood/bind-personal-id.d.ts +55 -0
  79. package/dist/personhood/bind-personal-id.js +12 -0
  80. package/dist/personhood/bootstrap.d.ts +85 -0
  81. package/dist/personhood/bootstrap.js +245 -0
  82. package/dist/personhood/claim-pgas.d.ts +61 -0
  83. package/dist/personhood/claim-pgas.js +12 -0
  84. package/dist/personhood/constants.d.ts +23 -0
  85. package/dist/personhood/constants.js +22 -0
  86. package/dist/personhood/encoding.d.ts +49 -0
  87. package/dist/personhood/encoding.js +24 -0
  88. package/dist/personhood/hashing.d.ts +4 -0
  89. package/dist/personhood/hashing.js +8 -0
  90. package/dist/personhood/member-key.d.ts +12 -0
  91. package/dist/personhood/member-key.js +10 -0
  92. package/dist/personhood/people-client.d.ts +14 -0
  93. package/dist/personhood/people-client.js +48 -0
  94. package/dist/personhood/reprove.d.ts +43 -0
  95. package/dist/personhood/reprove.js +225 -0
  96. package/dist/pool.d.ts +51 -0
  97. package/dist/pool.js +30 -0
  98. package/dist/run-state.d.ts +22 -0
  99. package/dist/run-state.js +20 -0
  100. package/dist/telemetry.d.ts +56 -0
  101. package/dist/telemetry.js +71 -0
  102. package/dist/version-check.d.ts +38 -0
  103. package/dist/version-check.js +30 -0
  104. package/docs/bootstrap.md +49 -0
  105. package/docs/e2e-bootstrap.md +154 -0
  106. package/docs/telemetry.md +62 -0
  107. package/docs/testing.md +44 -0
  108. package/package.json +82 -0
  109. package/tools/release-retry-wrapper.mjs +74 -0
@@ -0,0 +1,48 @@
1
+ import {
2
+ WS_HEARTBEAT_TIMEOUT_MS
3
+ } from "../chunk-DNXH4QTI.js";
4
+ import "../chunk-QMYW3D6E.js";
5
+ import "../chunk-MFTODIIT.js";
6
+ import "../chunk-KJH2T5TQ.js";
7
+ import {
8
+ loadEnvironments
9
+ } from "../chunk-OITUIM2E.js";
10
+ import "../chunk-ZOC4GITL.js";
11
+
12
+ // src/personhood/people-client.ts
13
+ import { createClient } from "polkadot-api";
14
+ import { getWsProvider } from "polkadot-api/ws";
15
+ async function connectPeopleClient(environmentId) {
16
+ const { doc } = await loadEnvironments();
17
+ const peopleChain = doc.chains.find((c) => c.id === "people");
18
+ if (!peopleChain) {
19
+ throw new Error(
20
+ `environments.json has no 'people' chain entry for env '${environmentId}'`
21
+ );
22
+ }
23
+ const entry = peopleChain.endpoints[environmentId];
24
+ if (!entry) {
25
+ throw new Error(
26
+ `No People-chain endpoint for environment '${environmentId}'. Bootstrap is only available on paseo-next-v2.`
27
+ );
28
+ }
29
+ const rawWss = entry.wss;
30
+ const wss = Array.isArray(rawWss) ? rawWss[0] : rawWss;
31
+ const client = createClient(
32
+ getWsProvider(wss, { heartbeatTimeout: WS_HEARTBEAT_TIMEOUT_MS })
33
+ );
34
+ const unsafeApi = client.getUnsafeApi();
35
+ return {
36
+ client,
37
+ unsafeApi,
38
+ disconnect: () => {
39
+ try {
40
+ client.destroy();
41
+ } catch {
42
+ }
43
+ }
44
+ };
45
+ }
46
+ export {
47
+ connectPeopleClient
48
+ };
@@ -0,0 +1,43 @@
1
+ import { SS58String, PolkadotSigner } from 'polkadot-api';
2
+
3
+ type ReproveAliasErrorKind = "NoStoredAlias" | "NotPaid" | "RingRootNotFound" | "RevisionNotAdvanced" | "AliasMismatch" | "NotARecognizedPerson" | "BadProof" | "DispatchError" | "RpcError" | "ClientError" | "Unknown";
4
+ declare class ReproveAliasError extends Error {
5
+ readonly kind: ReproveAliasErrorKind;
6
+ readonly dispatchError?: unknown;
7
+ constructor(message: string, options?: ErrorOptions & {
8
+ kind?: ReproveAliasErrorKind;
9
+ dispatchError?: unknown;
10
+ });
11
+ }
12
+ type RingExponent = 9 | 10 | 14;
13
+ interface BuildRingProofInput {
14
+ ringExponent: RingExponent;
15
+ members: Uint8Array;
16
+ context: Uint8Array;
17
+ msg: Uint8Array;
18
+ }
19
+ type BuildRingProof = (input: BuildRingProofInput) => Promise<{
20
+ proof: Uint8Array;
21
+ alias: Uint8Array;
22
+ }>;
23
+ interface ReproveAliasProgress {
24
+ onBroadcasted?: () => void;
25
+ onBestBlock?: (blockHash: string) => void;
26
+ }
27
+ interface ReproveAliasParams {
28
+ peopleUnsafeApi: unknown;
29
+ ahUnsafeApi: unknown;
30
+ account: SS58String;
31
+ memberKey: Uint8Array;
32
+ signCall: PolkadotSigner;
33
+ buildRingProof: BuildRingProof;
34
+ progress?: ReproveAliasProgress;
35
+ }
36
+ interface ReproveAliasResult {
37
+ blockHash: string;
38
+ oldRevision: number;
39
+ newRevision: number;
40
+ }
41
+ declare const reproveAliasToAccount: ({ peopleUnsafeApi, ahUnsafeApi, account, memberKey, signCall, buildRingProof, progress, }: ReproveAliasParams) => Promise<ReproveAliasResult>;
42
+
43
+ export { type BuildRingProof, type BuildRingProofInput, ReproveAliasError, type ReproveAliasErrorKind, type ReproveAliasParams, type ReproveAliasProgress, type ReproveAliasResult, type RingExponent, reproveAliasToAccount };
@@ -0,0 +1,225 @@
1
+ import {
2
+ PAID_PROOF_TAG,
3
+ PEOPLE_MEMBER_IDENTIFIER_HEX,
4
+ PROOF_BYTES
5
+ } from "../chunk-T7EEVWNU.js";
6
+ import {
7
+ blake2_256,
8
+ bytesToHex,
9
+ concatBytes,
10
+ encodeMembers,
11
+ hexToBytes
12
+ } from "../chunk-ZYVGHDMU.js";
13
+
14
+ // src/personhood/reprove.ts
15
+ import { getSs58AddressInfo } from "polkadot-api";
16
+ var ReproveAliasError = class extends Error {
17
+ kind;
18
+ dispatchError;
19
+ constructor(message, options = {}) {
20
+ super(message, options);
21
+ this.name = "ReproveAliasError";
22
+ this.kind = options.kind ?? "Unknown";
23
+ this.dispatchError = options.dispatchError;
24
+ }
25
+ };
26
+ var reproveAliasToAccount = async ({
27
+ peopleUnsafeApi,
28
+ ahUnsafeApi,
29
+ account,
30
+ memberKey,
31
+ signCall,
32
+ buildRingProof,
33
+ progress
34
+ }) => {
35
+ const people = peopleUnsafeApi;
36
+ const ah = ahUnsafeApi;
37
+ if (memberKey.length !== 32) {
38
+ throw new ReproveAliasError("memberKey must be 32 bytes", {
39
+ kind: "ClientError"
40
+ });
41
+ }
42
+ const stored = await ah.query.AliasAccounts.AccountToAlias.getValue(
43
+ account,
44
+ { at: "best" }
45
+ );
46
+ if (!stored) {
47
+ throw new ReproveAliasError(
48
+ "no AccountToAlias row for this account \u2014 bind first",
49
+ { kind: "NoStoredAlias" }
50
+ );
51
+ }
52
+ if (!stored.paid) {
53
+ throw new ReproveAliasError(
54
+ "AccountToAlias row is not paid \u2014 reprove_alias_account is only for paid aliases",
55
+ { kind: "NotPaid" }
56
+ );
57
+ }
58
+ const contextBytes = hexToBytes(stored.ca.context);
59
+ const storedRevision = stored.revision;
60
+ const storedRing = stored.ring;
61
+ const storedAliasHex = stored.ca.alias.toLowerCase();
62
+ const position = await people.query.Members.Members.getValue(
63
+ PEOPLE_MEMBER_IDENTIFIER_HEX,
64
+ bytesToHex(memberKey),
65
+ { at: "best" }
66
+ );
67
+ if (!position || position.type !== "Included") {
68
+ throw new ReproveAliasError(
69
+ `member position is '${position?.type ?? "absent"}', expected 'Included'`,
70
+ { kind: "NotARecognizedPerson" }
71
+ );
72
+ }
73
+ const ringIndex = position.value.ring_index;
74
+ const allEntries = await people.query.Members.RingKeys.getEntries({
75
+ at: "best"
76
+ });
77
+ const pages = [];
78
+ const identHex = PEOPLE_MEMBER_IDENTIFIER_HEX.toLowerCase();
79
+ for (const entry of allEntries) {
80
+ if (entry.keyArgs[0].toLowerCase() !== identHex) continue;
81
+ if (Number(entry.keyArgs[1]) !== ringIndex) continue;
82
+ pages.push([Number(entry.keyArgs[2]), [...entry.value]]);
83
+ }
84
+ pages.sort((a, b) => a[0] - b[0]);
85
+ const ringKeys = pages.flatMap(([, ks]) => ks);
86
+ if (ringKeys.length === 0) {
87
+ throw new ReproveAliasError("ring has no members on People", {
88
+ kind: "ClientError"
89
+ });
90
+ }
91
+ const membersBytes = encodeMembers(ringKeys.map((k) => hexToBytes(k)));
92
+ const ringExp = await ah.constants.AliasAccounts.PeopleRingExponent();
93
+ const ringExponent = ringExp.type === "R2e9" ? 9 : ringExp.type === "R2e10" ? 10 : 14;
94
+ const ringRoots = await ah.query.MembersSubscriber.RingRoots.getValue(
95
+ stored.collection,
96
+ ringIndex,
97
+ { at: "best" }
98
+ );
99
+ if (!ringRoots || ringRoots.length === 0) {
100
+ throw new ReproveAliasError(
101
+ "AH has no RingRoots for this (collection, ring_index)",
102
+ { kind: "RingRootNotFound" }
103
+ );
104
+ }
105
+ const latest = ringRoots[ringRoots.length - 1];
106
+ const newRevision = latest.revision;
107
+ if (newRevision <= storedRevision && ringIndex === storedRing) {
108
+ throw new ReproveAliasError(
109
+ `latest revision ${newRevision} is not strictly greater than stored ${storedRevision} on the same ring`,
110
+ { kind: "RevisionNotAdvanced" }
111
+ );
112
+ }
113
+ const ss58Info = getSs58AddressInfo(account);
114
+ if (!ss58Info.isValid) {
115
+ throw new ReproveAliasError(`invalid SS58: ${account}`, {
116
+ kind: "ClientError"
117
+ });
118
+ }
119
+ const paidMsg = blake2_256(concatBytes(PAID_PROOF_TAG, ss58Info.publicKey));
120
+ const { proof, alias } = await buildRingProof({
121
+ ringExponent,
122
+ members: membersBytes,
123
+ context: contextBytes,
124
+ msg: paidMsg
125
+ });
126
+ if (proof.length !== PROOF_BYTES) {
127
+ throw new ReproveAliasError(
128
+ `ring proof must be ${PROOF_BYTES} bytes, got ${proof.length}`,
129
+ { kind: "ClientError" }
130
+ );
131
+ }
132
+ if (bytesToHex(alias).toLowerCase() !== storedAliasHex) {
133
+ throw new ReproveAliasError(
134
+ `regenerated alias ${bytesToHex(alias)} differs from stored ${storedAliasHex} \u2014 would fail ReproveMismatch`,
135
+ { kind: "AliasMismatch" }
136
+ );
137
+ }
138
+ const tx = ah.tx.AliasAccounts.reprove_alias_account({
139
+ proof: bytesToHex(proof),
140
+ ring_index: ringIndex,
141
+ ring_revision: newRevision
142
+ });
143
+ const blockHash = await new Promise((resolve, reject) => {
144
+ let settled = false;
145
+ const fail = (err) => {
146
+ if (settled) return;
147
+ settled = true;
148
+ reject(err);
149
+ };
150
+ const succeed = (h) => {
151
+ if (settled) return;
152
+ settled = true;
153
+ resolve(h);
154
+ };
155
+ tx.signSubmitAndWatch(signCall).subscribe({
156
+ next: (event) => {
157
+ if (settled) return;
158
+ const ev = event;
159
+ if (ev.type === "broadcasted") {
160
+ progress?.onBroadcasted?.();
161
+ return;
162
+ }
163
+ if (ev.type === "txBestBlocksState" && ev.found) {
164
+ if (ev.ok === false) {
165
+ fail(
166
+ new ReproveAliasError(
167
+ "reprove_alias_account dispatched but failed in-block",
168
+ {
169
+ kind: narrowDispatchError(ev.dispatchError),
170
+ dispatchError: ev.dispatchError
171
+ }
172
+ )
173
+ );
174
+ return;
175
+ }
176
+ if (ev.block) progress?.onBestBlock?.(ev.block.hash);
177
+ return;
178
+ }
179
+ if (ev.type === "finalized") {
180
+ if (ev.ok === false) {
181
+ fail(
182
+ new ReproveAliasError(
183
+ "reprove_alias_account failed at finalization",
184
+ {
185
+ kind: narrowDispatchError(ev.dispatchError),
186
+ dispatchError: ev.dispatchError
187
+ }
188
+ )
189
+ );
190
+ return;
191
+ }
192
+ if (ev.block) succeed(ev.block.hash);
193
+ }
194
+ },
195
+ error: (err) => {
196
+ fail(
197
+ err instanceof ReproveAliasError ? err : new ReproveAliasError(
198
+ err instanceof Error ? `RPC rejected extrinsic: ${err.message}` : "RPC error during submitAndWatch",
199
+ { cause: err, kind: "RpcError" }
200
+ )
201
+ );
202
+ }
203
+ });
204
+ });
205
+ return { blockHash, oldRevision: storedRevision, newRevision };
206
+ };
207
+ var narrowDispatchError = (dispatchError) => {
208
+ if (typeof dispatchError === "object" && dispatchError !== null && "type" in dispatchError) {
209
+ const d = dispatchError;
210
+ if (d.type === "Module" && typeof d.value === "object" && d.value !== null) {
211
+ const v = d.value;
212
+ if (v.type === "AliasAccounts") {
213
+ if (v.value?.type === "BadProof") return "BadProof";
214
+ if (v.value?.type === "ReproveMismatch") return "AliasMismatch";
215
+ if (v.value?.type === "AliasAccountAlreadySet")
216
+ return "RevisionNotAdvanced";
217
+ }
218
+ }
219
+ }
220
+ return "DispatchError";
221
+ };
222
+ export {
223
+ ReproveAliasError,
224
+ reproveAliasToAccount
225
+ };
package/dist/pool.d.ts ADDED
@@ -0,0 +1,51 @@
1
+ import { PolkadotSigner } from 'polkadot-api';
2
+
3
+ declare function formatPasBalance(plancks: bigint): string;
4
+ interface PoolAccount {
5
+ index: number;
6
+ path: string;
7
+ publicKey: Uint8Array;
8
+ signer: PolkadotSigner;
9
+ address: string;
10
+ }
11
+ interface PoolAuthorization extends PoolAccount {
12
+ transactions: bigint;
13
+ bytes: bigint;
14
+ expiration: number;
15
+ }
16
+ declare function derivePoolAccounts(poolSize?: number, mnemonic?: string): PoolAccount[];
17
+ interface AuthorizationCheck {
18
+ needs?: AuthorizationNeeds;
19
+ bulletinAuthorizeV2?: boolean;
20
+ }
21
+ declare function isAuthorizationSufficient(auth: any, currentBlock: number, check?: AuthorizationCheck): boolean;
22
+ interface SelectionResult {
23
+ account: PoolAuthorization;
24
+ eligibleCount: number;
25
+ }
26
+ declare function selectAccount(authorizations: PoolAuthorization[], random?: () => number, currentBlock?: number): SelectionResult | null;
27
+ declare function fetchPoolAuthorizations(api: any, accounts: PoolAccount[]): Promise<PoolAuthorization[]>;
28
+ interface AuthorizationNeeds {
29
+ txs: bigint;
30
+ bytes: bigint;
31
+ }
32
+ declare function computeTopUpTarget(current: {
33
+ transactions: bigint;
34
+ bytes: bigint;
35
+ }, needs: AuthorizationNeeds): {
36
+ transactions: bigint;
37
+ bytes: bigint;
38
+ } | null;
39
+ type TxRetryDecision = "retry" | "abort";
40
+ declare function classifyAliceTxError(err: unknown): TxRetryDecision;
41
+ declare function isTestnetSpecName(specName: string | undefined | null): boolean;
42
+ declare function detectTestnet(api: any): Promise<boolean>;
43
+ declare function _resetTestnetCacheForTests(): void;
44
+ declare function ensureAuthorized(api: any, address: string, label?: string, bulletinAuthorizeV2?: boolean, needs?: AuthorizationNeeds): Promise<void>;
45
+ declare function topUpBy(api: any, address: string, needs: AuthorizationNeeds, label?: string, bulletinAuthorizeV2?: boolean): Promise<void>;
46
+ interface BootstrapOptions {
47
+ bulletinAuthorizeV2?: boolean;
48
+ }
49
+ declare function bootstrapPool(bulletinRpc: string, poolSize?: number, mnemonic?: string, opts?: BootstrapOptions): Promise<void>;
50
+
51
+ export { type AuthorizationCheck, type AuthorizationNeeds, type BootstrapOptions, type PoolAccount, type PoolAuthorization, type SelectionResult, type TxRetryDecision, _resetTestnetCacheForTests, bootstrapPool, classifyAliceTxError, computeTopUpTarget, derivePoolAccounts, detectTestnet, ensureAuthorized, fetchPoolAuthorizations, formatPasBalance, isAuthorizationSufficient, isTestnetSpecName, selectAccount, topUpBy };
package/dist/pool.js ADDED
@@ -0,0 +1,30 @@
1
+ import {
2
+ _resetTestnetCacheForTests,
3
+ bootstrapPool,
4
+ classifyAliceTxError,
5
+ computeTopUpTarget,
6
+ derivePoolAccounts,
7
+ detectTestnet,
8
+ ensureAuthorized,
9
+ fetchPoolAuthorizations,
10
+ formatPasBalance,
11
+ isAuthorizationSufficient,
12
+ isTestnetSpecName,
13
+ selectAccount,
14
+ topUpBy
15
+ } from "./chunk-QMYW3D6E.js";
16
+ export {
17
+ _resetTestnetCacheForTests,
18
+ bootstrapPool,
19
+ classifyAliceTxError,
20
+ computeTopUpTarget,
21
+ derivePoolAccounts,
22
+ detectTestnet,
23
+ ensureAuthorized,
24
+ fetchPoolAuthorizations,
25
+ formatPasBalance,
26
+ isAuthorizationSufficient,
27
+ isTestnetSpecName,
28
+ selectAccount,
29
+ topUpBy
30
+ };
@@ -0,0 +1,22 @@
1
+ declare const VERSION: string;
2
+ type RunStatus = "running" | "succeeded" | "failed" | "crashed";
3
+ interface RunState {
4
+ status: RunStatus;
5
+ pid: number;
6
+ startedAt: number;
7
+ endedAt?: number;
8
+ toolVersion: string;
9
+ argv: string[];
10
+ lastPeakRssMb: number | null;
11
+ lastStage: string | null;
12
+ reason?: string;
13
+ }
14
+ declare function resolveStateDir(): string;
15
+ declare function stateFilePath(): string;
16
+ declare function loadRunState(): RunState | null;
17
+ declare function writeRunState(patch: Partial<RunState>): void;
18
+ declare function shouldSkipStaleWarning(prev: RunState): boolean;
19
+ declare function probablyOomRssMb(override?: number): number;
20
+ declare function shouldShowOomHint(prev: RunState): boolean;
21
+
22
+ export { type RunState, type RunStatus, VERSION, loadRunState, probablyOomRssMb, resolveStateDir, shouldShowOomHint, shouldSkipStaleWarning, stateFilePath, writeRunState };
@@ -0,0 +1,20 @@
1
+ import {
2
+ VERSION,
3
+ loadRunState,
4
+ probablyOomRssMb,
5
+ resolveStateDir,
6
+ shouldShowOomHint,
7
+ shouldSkipStaleWarning,
8
+ stateFilePath,
9
+ writeRunState
10
+ } from "./chunk-KJH2T5TQ.js";
11
+ export {
12
+ VERSION,
13
+ loadRunState,
14
+ probablyOomRssMb,
15
+ resolveStateDir,
16
+ shouldShowOomHint,
17
+ shouldSkipStaleWarning,
18
+ stateFilePath,
19
+ writeRunState
20
+ };
@@ -0,0 +1,56 @@
1
+ import * as _sentry_node from '@sentry/node';
2
+ import { DeployContextForReport } from './memory-report.js';
3
+ import 'node:v8';
4
+
5
+ declare const VERSION: string;
6
+ type SentryModule = typeof _sentry_node | null;
7
+ interface InternalContextSignals {
8
+ githubRepository?: string;
9
+ runnerName?: string;
10
+ gitRemote?: string;
11
+ hostApp?: string;
12
+ }
13
+ declare function isInternalContextFromSignals(signals: InternalContextSignals): boolean;
14
+ declare function isInternalContext(): boolean;
15
+ declare function scrubPaths(msg: string): string;
16
+ declare function truncateAddress(ss58: string | undefined): string | undefined;
17
+ declare function sanitizeBranch(name: string | undefined): string | undefined;
18
+ declare function sanitizeRepo(slug: string | undefined): string | undefined;
19
+ declare function setRunStateActive(v: boolean): void;
20
+ declare function markRelaunchOomHintShown(): void;
21
+ declare function closeTelemetry(timeoutMs: number): Promise<void>;
22
+ declare function initTelemetry(): void;
23
+ declare function resolveRepo(domain: string): string;
24
+ declare function resolveRunner(): string;
25
+ declare function resolveRunnerType(): string;
26
+ declare function getDeployAttributes(domain: string): Record<string, string | number | boolean | undefined>;
27
+ declare function isExpectedError(msg: string): boolean;
28
+ type DeployErrorCategory = 'user' | 'environment' | 'internal' | 'unknown';
29
+ declare function classifyDeployError(msg: string): DeployErrorCategory;
30
+ declare function classifySadReason(message: string): string;
31
+ declare function computeDeployOutcome(errorCategory: DeployErrorCategory | null, isSad: boolean, sadReason: string): string;
32
+ type DeployErrorKind = 'contract-revert' | 'chain-timeout' | 'nonce-stale' | 'connection' | 'naming.pop_required' | 'naming.already_owned' | 'naming.subdomain_orphan' | 'verify.contenthash_mismatch' | 'verify.dagpb_not_finalised' | 'network.recovery_exhausted' | 'chain.api_timeout' | 'tool.invariant' | 'unknown';
33
+ declare function classifyErrorKind(msg: string): DeployErrorKind;
34
+ declare function sanitizeErrorMessage(msg: string): string;
35
+ /**
36
+ * Classify an error message's *shape* (length, presence of certain patterns)
37
+ * without excerpting content. The result is a comma-joined list of tags;
38
+ * future analysis of scrubbed events will use this to identify which content
39
+ * shape triggered Sentry's PII scrubber, so we can build a real sanitiser.
40
+ */
41
+ declare function analyseErrorPattern(msg: string): string;
42
+ declare function withSpan<T>(op: string, description: string, attributes: Record<string, string | number | boolean | undefined>, fn: () => T | Promise<T>): Promise<T>;
43
+ declare function sampleMemory(stage: string): void;
44
+ declare function withDeploySpan<T>(domain: string, fn: () => T | Promise<T>): Promise<T>;
45
+ declare function setDeployReportContext(patch: Partial<DeployContextForReport> & {
46
+ outputDir?: string;
47
+ }): void;
48
+ declare function setDeployAttribute(key: string, value: string | number | boolean): void;
49
+ declare function __setDeployRootSpanForTest(span: any | null): void;
50
+ declare function __setSentryForTest(stub: any): SentryModule;
51
+ declare function getCurrentSentryTraceId(): string | undefined;
52
+ declare function setDeploySentryTag(key: string, value: string): void;
53
+ declare function captureWarning(message: string, context?: Record<string, unknown>): void;
54
+ declare function flush(): Promise<void>;
55
+
56
+ export { type DeployErrorCategory, type DeployErrorKind, type InternalContextSignals, VERSION, __setDeployRootSpanForTest, __setSentryForTest, analyseErrorPattern, captureWarning, classifyDeployError, classifyErrorKind, classifySadReason, closeTelemetry, computeDeployOutcome, flush, getCurrentSentryTraceId, getDeployAttributes, initTelemetry, isExpectedError, isInternalContext, isInternalContextFromSignals, markRelaunchOomHintShown, resolveRepo, resolveRunner, resolveRunnerType, sampleMemory, sanitizeBranch, sanitizeErrorMessage, sanitizeRepo, scrubPaths, setDeployAttribute, setDeployReportContext, setDeploySentryTag, setRunStateActive, truncateAddress, withDeploySpan, withSpan };
@@ -0,0 +1,71 @@
1
+ import {
2
+ VERSION,
3
+ __setDeployRootSpanForTest,
4
+ __setSentryForTest,
5
+ analyseErrorPattern,
6
+ captureWarning,
7
+ classifyDeployError,
8
+ classifyErrorKind,
9
+ classifySadReason,
10
+ closeTelemetry,
11
+ computeDeployOutcome,
12
+ flush,
13
+ getCurrentSentryTraceId,
14
+ getDeployAttributes,
15
+ initTelemetry,
16
+ isExpectedError,
17
+ isInternalContext,
18
+ isInternalContextFromSignals,
19
+ markRelaunchOomHintShown,
20
+ resolveRepo,
21
+ resolveRunner,
22
+ resolveRunnerType,
23
+ sampleMemory,
24
+ sanitizeBranch,
25
+ sanitizeErrorMessage,
26
+ sanitizeRepo,
27
+ scrubPaths,
28
+ setDeployAttribute,
29
+ setDeployReportContext,
30
+ setDeploySentryTag,
31
+ setRunStateActive,
32
+ truncateAddress,
33
+ withDeploySpan,
34
+ withSpan
35
+ } from "./chunk-MFTODIIT.js";
36
+ import "./chunk-KJH2T5TQ.js";
37
+ export {
38
+ VERSION,
39
+ __setDeployRootSpanForTest,
40
+ __setSentryForTest,
41
+ analyseErrorPattern,
42
+ captureWarning,
43
+ classifyDeployError,
44
+ classifyErrorKind,
45
+ classifySadReason,
46
+ closeTelemetry,
47
+ computeDeployOutcome,
48
+ flush,
49
+ getCurrentSentryTraceId,
50
+ getDeployAttributes,
51
+ initTelemetry,
52
+ isExpectedError,
53
+ isInternalContext,
54
+ isInternalContextFromSignals,
55
+ markRelaunchOomHintShown,
56
+ resolveRepo,
57
+ resolveRunner,
58
+ resolveRunnerType,
59
+ sampleMemory,
60
+ sanitizeBranch,
61
+ sanitizeErrorMessage,
62
+ sanitizeRepo,
63
+ scrubPaths,
64
+ setDeployAttribute,
65
+ setDeployReportContext,
66
+ setDeploySentryTag,
67
+ setRunStateActive,
68
+ truncateAddress,
69
+ withDeploySpan,
70
+ withSpan
71
+ };
@@ -0,0 +1,38 @@
1
+ import { Readable } from 'node:stream';
2
+
3
+ interface VersionInfo {
4
+ latest: string;
5
+ minimumFromRegistry: string | null;
6
+ minimumFromKillSwitch: string | null;
7
+ killSwitchMessage: string | null;
8
+ }
9
+ declare function checkNodeVersion(enginesNode: string, currentVersion: string): string | null;
10
+ declare function compareSemver(a: string, b: string): number;
11
+ declare function isPreReleaseVersion(version: string): boolean;
12
+ declare function preReleaseWarning(version: string): string | null;
13
+ declare function fetchVersionInfo(): Promise<VersionInfo | null>;
14
+ declare function handlePreflightVersionCheck(info: VersionInfo | null): "abort" | "nudge" | "ok";
15
+ declare function isInternalUser(cwd?: string): boolean;
16
+ declare function isInteractive(): boolean;
17
+ declare function promptYesNo(question: string, input?: Readable): Promise<boolean>;
18
+ declare function classifyErrorArea(msg: string): string | null;
19
+ type VersionVerdict = {
20
+ action: "forced_update";
21
+ currentVersion: string;
22
+ minimumVersion: string;
23
+ message: string | null;
24
+ } | {
25
+ action: "suggest_update";
26
+ currentVersion: string;
27
+ latestVersion: string;
28
+ internal: boolean;
29
+ } | {
30
+ action: "bug_report";
31
+ internal: boolean;
32
+ } | {
33
+ action: "none";
34
+ };
35
+ declare function assessVersion(currentVersion: string, info: VersionInfo, internal: boolean): VersionVerdict;
36
+ declare function handleFailedDeploy(error: Error): Promise<void>;
37
+
38
+ export { type VersionVerdict, assessVersion, checkNodeVersion, classifyErrorArea, compareSemver, fetchVersionInfo, handleFailedDeploy, handlePreflightVersionCheck, isInteractive, isInternalUser, isPreReleaseVersion, preReleaseWarning, promptYesNo };
@@ -0,0 +1,30 @@
1
+ import {
2
+ assessVersion,
3
+ checkNodeVersion,
4
+ classifyErrorArea,
5
+ compareSemver,
6
+ fetchVersionInfo,
7
+ handleFailedDeploy,
8
+ handlePreflightVersionCheck,
9
+ isInteractive,
10
+ isInternalUser,
11
+ isPreReleaseVersion,
12
+ preReleaseWarning,
13
+ promptYesNo
14
+ } from "./chunk-43HLT335.js";
15
+ import "./chunk-MFTODIIT.js";
16
+ import "./chunk-KJH2T5TQ.js";
17
+ export {
18
+ assessVersion,
19
+ checkNodeVersion,
20
+ classifyErrorArea,
21
+ compareSemver,
22
+ fetchVersionInfo,
23
+ handleFailedDeploy,
24
+ handlePreflightVersionCheck,
25
+ isInteractive,
26
+ isInternalUser,
27
+ isPreReleaseVersion,
28
+ preReleaseWarning,
29
+ promptYesNo
30
+ };
@@ -0,0 +1,49 @@
1
+ # bulletin-bootstrap
2
+
3
+ `bulletin-bootstrap` is the operator CLI for initializing Bulletin pool accounts. It is separate from `bulletin-deploy` on purpose: deploys are the normal user path, bootstrap is an admin/setup operation.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ bulletin-bootstrap
9
+ ```
10
+
11
+ Options:
12
+
13
+ | Flag | What it does |
14
+ |---|---|
15
+ | `--rpc wss://...` | Override the Bulletin RPC endpoint. Also readable from `BULLETIN_RPC`. |
16
+ | `--pool-size N` | Number of derived pool accounts to initialize. Default: `10`. |
17
+ | `--mnemonic "..."` | Root mnemonic used to derive the pool accounts. Also readable from `BULLETIN_POOL_MNEMONIC`, then `MNEMONIC`. |
18
+ | `--version` | Print the CLI version. |
19
+ | `--help` | Show help. |
20
+
21
+ ## What it does
22
+
23
+ The command derives the pool account set and initializes the on-chain authorization state needed for Bulletin uploads.
24
+
25
+ Use it when:
26
+
27
+ - you are bringing up a fresh pool on a testnet
28
+ - the shared uploader pool has not been authorized yet
29
+ - you want to pre-initialize a non-default pool mnemonic
30
+
31
+ Do not use it as part of routine deploys. Normal deploys go through `bulletin-deploy`.
32
+
33
+ ## Examples
34
+
35
+ ```bash
36
+ # Default testnet pool against the default RPC
37
+ bulletin-bootstrap
38
+
39
+ # Different RPC and larger pool
40
+ bulletin-bootstrap --rpc wss://custom-bulletin.example.com --pool-size 20
41
+
42
+ # Explicit pool mnemonic
43
+ bulletin-bootstrap --mnemonic "..."
44
+ ```
45
+
46
+ ## Related Docs
47
+
48
+ - [Main README](../README.md)
49
+ - [E2E test setup](./e2e-bootstrap.md)