@artblocks/abx-indexer 0.1.0-alpha.3 → 0.1.0-alpha.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,645 @@
1
+ # @artblocks/abx-indexer
2
+
3
+ ## 0.1.0-alpha.30
4
+
5
+ ### Minor Changes
6
+
7
+ - c198237: Closes the remaining 2026-08-27 w7 agent sweep backlog (B60-B65): a new command, a real behavior
8
+ change, and several truthfulness/legibility fixes.
9
+
10
+ - **`abx remote set <name> --url <url>`** — the third-party twin of `abx auth login`. Installs
11
+ `ABX_REMOTE_<NAME>_URL`/`_TOKEN` into `.env` for any hosted metadata provider, not just the
12
+ first-party `abx` remote. The token is read from stdin (piped, or a TTY prompt) — never a
13
+ command-line argument, never printed — and re-running replaces the pair in place rather than
14
+ duplicating it. Reuses `auth login`'s own safety rails (symlink/git-tracked/unignored refusal,
15
+ atomic write) via newly-exported `saveEnvSecret`/`assertPrivateEnvPath`.
16
+ - **`abx scaffold solidity [<dir>]`** replaces the proposed `scaffold-minter-hook` with one Foundry
17
+ workspace for ABX's real Solidity extension surfaces. Renderers and configure/transfer/augment
18
+ hooks remain separate deployable roles; canonical ERC-721/ERC-1155 minters are imported rather than
19
+ reinvented. The unsafe burn-to-combine example was removed.
20
+ - **`abx-contracts~2.0.0`** is the canonical Soldeer package boundary (B49): interfaces,
21
+ implementations, minters and reference hooks ship from the existing contracts source tree, with an
22
+ exact compatibility version. Generated projects no longer vendor drift-prone interface copies.
23
+ B50 is resolved without a mock protocol: reference-hook tests deploy a real canonical SeriesCode
24
+ clone and exercise schema auth, empty-blob refusal, hook ordering and transfers against it.
25
+ - **`.env` duplicate keys are now last-wins**, matching conventional dotenv tooling instead of the
26
+ previous (surprising, backwards) first-wins behavior. `parseEnvContent` keeps the last value at the
27
+ key's original position; the printed warning updated to match.
28
+ - **`abx state` now says when it can't enumerate PostParams**, instead of silently showing nothing —
29
+ a non-canonical/pre-enumeration contract used to read as "confirmed no params" when it actually meant
30
+ "this node couldn't check." New human-readable line + `params.enumerable` in `--json`.
31
+ - **A throttled progress line during a large `abx add`/`abx verify` scan** — a range-capped RPC's scan
32
+ could run 15+ minutes with zero output after one line up front. Now prints `… still scanning:
33
+ N/total blocks (X%)` periodically via a new `onChunk` hook threaded through
34
+ `getLogsAdaptive`→`reconstructProject`/`reconstructIncremental`→the indexer's `reindex()`.
35
+ - **Three smaller truthfulness fixes**: `abx remote <url>` now flags a loopback descriptor
36
+ `baseUrl` the same way it already flags an unsupported chain; `configure-param` now notes when the
37
+ canonical display differs from what was typed (a bare `ff7f50` normalizing to `#ff7f50`, a Select
38
+ index resolving to its label); and owner-op `--dry-run --json` now emits the prepared transaction,
39
+ expected signer, signing lane, and simulation result as structured data.
40
+
41
+ ### Patch Changes
42
+
43
+ - Updated dependencies [c198237]
44
+ - @artblocks/abx-sdk@0.1.0-alpha.29
45
+
46
+ ## 0.1.0-alpha.29
47
+
48
+ ### Patch Changes
49
+
50
+ - c5e0d84: Published package `homepage` and `bugs` fields now point at docs.abx.io instead of a private GitHub
51
+ repo that 404s. File reports with `abx feedback`; `npm bugs` no longer names a repository the public
52
+ cannot open.
53
+
54
+ Reported in the 2026-08-27 tester batch (feedback 40142396).
55
+
56
+ - Updated dependencies [c5e0d84]
57
+ - Updated dependencies [c5e0d84]
58
+ - @artblocks/abx-sdk@0.1.0-alpha.28
59
+
60
+ ## 0.1.0-alpha.28
61
+
62
+ ### Patch Changes
63
+
64
+ - Updated dependencies [4072f0c]
65
+ - @artblocks/abx-sdk@0.1.0-alpha.27
66
+
67
+ ## 0.1.0-alpha.27
68
+
69
+ ### Patch Changes
70
+
71
+ - Updated dependencies [b182f23]
72
+ - @artblocks/abx-sdk@0.1.0-alpha.26
73
+
74
+ ## 0.1.0-alpha.26
75
+
76
+ ### Patch Changes
77
+
78
+ - Updated dependencies [8f2f78a]
79
+ - @artblocks/abx-sdk@0.1.0-alpha.25
80
+
81
+ ## 0.1.0-alpha.25
82
+
83
+ ### Patch Changes
84
+
85
+ - Updated dependencies [61503c3]
86
+ - @artblocks/abx-sdk@0.1.0-alpha.24
87
+
88
+ ## 0.1.0-alpha.24
89
+
90
+ ### Patch Changes
91
+
92
+ - bd77ba2: Correct the Node floor to 22.13, and refuse to start with a remedy instead of a stack trace.
93
+
94
+ Every package declared `engines.node: ">=22.5.0"` — the version `node:sqlite` was **added**, not the
95
+ version it became usable. It shipped in v22.5.0 behind `--experimental-sqlite` and lost the flag in
96
+ v22.13.0 / v23.4.0. So `npm i -g @artblocks/abx-cli` on Node 22.5 installed silently (the engine
97
+ range was satisfied) and then `abx doctor` — the first command we tell everyone to run — died with a
98
+ raw `ERR_UNKNOWN_BUILTIN_MODULE: No such built-in module: node:sqlite` stack trace naming neither
99
+ abx nor a fix. Reported 2026-08-24; the floor is now `>=22.13.0` everywhere, so npm warns at install
100
+ time.
101
+
102
+ The crash happened while ESM _linked_ `main.ts`'s import graph (`output.ts` →
103
+ `@artblocks/abx-indexer` → `node:sqlite`), before any of our code ran, so no guard inside the CLI
104
+ could have caught it. The published binary is now a deliberately import-free shim (`dist/bin.js`)
105
+ that probes for `node:sqlite` and hands off to `main.js` — it prints the running version, the real
106
+ floor, and the upgrade command. It probes the **capability**, not the version number: an old Node
107
+ launched with `NODE_OPTIONS=--experimental-sqlite` genuinely works, and refusing that would be a
108
+ false negative. `engines` states what we support; the guard blocks only what is actually broken.
109
+
110
+ `abx doctor`'s header now also reports the running Node, since its output is what people paste when
111
+ something is wrong.
112
+
113
+ - Updated dependencies [bd77ba2]
114
+ - @artblocks/abx-sdk@0.1.0-alpha.23
115
+
116
+ ## 0.1.0-alpha.23
117
+
118
+ ### Patch Changes
119
+
120
+ - Updated dependencies [993e095]
121
+ - @artblocks/abx-sdk@0.1.0-alpha.22
122
+
123
+ ## 0.1.0-alpha.22
124
+
125
+ ### Patch Changes
126
+
127
+ - Updated dependencies [c9f7aeb]
128
+ - @artblocks/abx-sdk@0.1.0-alpha.21
129
+
130
+ ## 0.1.0-alpha.21
131
+
132
+ ### Patch Changes
133
+
134
+ - Updated dependencies [84ca9dd]
135
+ - Updated dependencies [84ca9dd]
136
+ - @artblocks/abx-sdk@0.1.0-alpha.20
137
+
138
+ ## 0.1.0-alpha.20
139
+
140
+ ### Patch Changes
141
+
142
+ - Updated dependencies [b1c333d]
143
+ - Updated dependencies [b1c333d]
144
+ - @artblocks/abx-sdk@0.1.0-alpha.19
145
+
146
+ ## 0.1.0-alpha.19
147
+
148
+ ### Patch Changes
149
+
150
+ - Updated dependencies [77a6248]
151
+ - Updated dependencies [77a6248]
152
+ - @artblocks/abx-sdk@0.1.0-alpha.18
153
+
154
+ ## 0.1.0-alpha.18
155
+
156
+ ### Patch Changes
157
+
158
+ - 5b29f53: Drop-in for every reconstruct caller; new exports for hosted/self-host watch loops so they stop
159
+ reimplementing `eth_getLogs` chunking and a second per-project fetch.
160
+
161
+ **`getLogsAdaptive` is public and accepts `Address | Address[]`.** Address-list chunking defaults to
162
+ 1000 (ordinary RPC tier cap) via `addressBatch` — an RPC opinion, not a protocol constant; `0`
163
+ disables splitting. Per-tick block windows stay with the watcher (the reference one still uses 5000).
164
+
165
+ **`reconstructFromLogs(client, prior, logs, {toBlock})`** is the fold / head-read half of
166
+ `reconstructIncremental` given logs the caller already holds. `toBlock` is the inclusive scan head
167
+ those logs cover, so a capped window cannot stamp past the last block actually scanned.
168
+ `reconstructIncremental` is now a getLogs + that function.
169
+
170
+ **A Transfer no longer re-downloads every on-chain script chunk.** Chunk content has no log;
171
+ `ScriptUpdated` is the ping. `applyHeadReads` keeps the prior digest unless that ping is in `fresh`
172
+ (or the prior digest is missing). Same change helps the single-address path.
173
+
174
+ The reference token-api watcher now calls `getLogsAdaptive` for the registered set and hands each
175
+ touched project's logs to `reindex({logs, toBlock})`, so the watch tick is the only getLogs.
176
+
177
+ - Updated dependencies [c5b8ec3]
178
+ - Updated dependencies [5b29f53]
179
+ - @artblocks/abx-sdk@0.1.0-alpha.17
180
+
181
+ ## 0.1.0-alpha.17
182
+
183
+ ### Minor Changes
184
+
185
+ - b5744a1: An RPC that has pruned its log history is now detected, named, and routed around
186
+
187
+ A public endpoint that no longer holds old logs does not fail your scan — it answers `eth_getLogs`
188
+ with `[]` and HTTP 200, which is a success. Everything downstream believed it:
189
+
190
+ - **`abx doctor` graded it `best`.** The archive probe was
191
+ `getLogs({address: zeroAddress, fromBlock: old, toBlock: old})` and counted any non-throw as archive
192
+ access — but `zeroAddress` never emits logs, so an empty result is exactly what a _perfect_ archive
193
+ node returns too. The assertion could not fail; it only ever caught endpoints that _error_ on old
194
+ blocks. `ARCHIVE_DEPTH` was also 100k blocks, which on a 2-second chain is inside the retained window
195
+ of the very endpoints that prune.
196
+ - **The client never failed over.** The read transport is a viem `fallback` across every configured
197
+ endpoint, and `fallback` rotates on an _error_. So every retry asked the same endpoint the same
198
+ question, and a project whose logs sit ready on the SECOND configured endpoint reconstructed as
199
+ empty.
200
+ - **`abx add` then registered the project with no state at all**, after grinding half a million blocks,
201
+ and suggested re-running `--full` "in a minute" — advice that can never work for a pruned index.
202
+
203
+ Measured on the two default Base Sepolia endpoints, same address and same window: one returns zero
204
+ logs for the project's entire history, the other returns them instantly. Ethereum Sepolia's keyless
205
+ default endpoint shows the same shape past a few hundred thousand blocks.
206
+
207
+ - **The probe asserts on something that must come back.** Blocks are retained by everyone; receipts
208
+ and the log index are what get pruned. `probeHistoryAt` (new SDK export) reads the probe block, asks
209
+ for one of its transactions' receipts, and — when that receipt carries a log — requires `getLogs` to
210
+ return that same log. No hardcoded address, no fixture block. `ARCHIVE_DEPTH` is now 500k.
211
+ It fails **safe**: a probe block with no transactions, or whose transactions logged nothing, keeps the
212
+ old lenient verdict rather than inventing a failure.
213
+ - **`abx doctor` names a reachable endpoint that can't serve history**, with the fault and the fix
214
+ ("history pruned ~500000 blocks back … list a full-archive endpoint FIRST in `ABX_RPC_URLS_<CHAIN>`").
215
+ Collapsing to the best endpoint hid this, and ordering is what decides who answers the scan.
216
+ - **An empty scan now retries each endpoint on its own** before giving up, and says which one served
217
+ the logs. Cheap by construction: each endpoint is first asked whether it holds history at _this
218
+ project's_ deploy block — three calls — and only one that passes gets a scan.
219
+ - **`SelfHostIndexer.reindex(address, {rpcUrl})`** pins a single endpoint instead of the pool, which is
220
+ what makes that rotation expressible. Clients are pooled per (chain, endpoint), so the default path
221
+ is unchanged.
222
+ - The final failure message now separates the two cases it had merged: a project you _just_ deployed
223
+ (transient, retry) from one that is not new (retention — check `abx doctor`).
224
+
225
+ Found by direct probing during the 2026-08-17 agent sweep, after an `abx add` of a 12-day-old Base
226
+ Sepolia edition reconstructed zero of its 18 events.
227
+
228
+ ### Patch Changes
229
+
230
+ - Updated dependencies [9c287c0]
231
+ - Updated dependencies [b5744a1]
232
+ - Updated dependencies [9c287c0]
233
+ - @artblocks/abx-sdk@0.1.0-alpha.16
234
+
235
+ ## 0.1.0-alpha.16
236
+
237
+ ### Minor Changes
238
+
239
+ - 7fec2d7: An edition's per-id cap now folds from the log, so a capped edition stops reporting itself as open
240
+
241
+ `DefaultMaxSupplySet` — added in the contract-audit release precisely so the log could tell an open
242
+ edition from a capped one — reached the ABI and stopped there. `reconstruct.ts` had no fold case, so
243
+ the collection-wide default never landed in `ProjectState`, and **the common shape was the broken
244
+ one**: `--copies N` sets the cap at `initialize` and never calls `setMaxSupply`, so no id has a
245
+ `MaxSupplyUpdated` of its own and every capped edition ever deployed folded as _uncapped_. The
246
+ head-read lane (`listTokens`, which calls `maxSupply(id)`) said `N` the whole time — one field name,
247
+ two answers, on the value that decides whether a buy button renders. Found by the abx-services team
248
+ while upgrading their resolver/indexer to this release.
249
+
250
+ - **`ProjectState.defaultMaxSupply`** — the collection-wide per-id default (`'0'` = open; `null` ⇒ not
251
+ an edition). The 1155 analogue of `maxInvocations`.
252
+ - **`TokenState.maxSupply` is now the _effective_ cap** — an id's own override, else that default —
253
+ and so equals `maxSupply(id)` on chain and its head-read twin `TokenRow.maxSupply`. Previously it
254
+ was the override alone, and absent otherwise.
255
+ - **`TokenState.maxSupplyOverridden`** — whether this id has ever been explicitly overridden. The
256
+ distinction the on-chain getter cannot express (`maxSupply(id)` returns `0` for both "never capped"
257
+ and "deliberately closed") and the log now can, plus a signal that the monotonic never-increase rule
258
+ is in force for that id.
259
+ - **`editionCapOf(token)`** — new SDK export returning `{kind:'open'} | {kind:'capped', cap} |
260
+ {kind:'closed'}`, so nothing re-derives the rule. Used by the dashboard and `abx tokens`; pass a
261
+ head-read row and a `'0'` cap reads `open`, which is all a state read can honestly say.
262
+ - **The dashboard stops lying twice.** It tested `maxSupply` for truthiness: a `--copies 10` id read
263
+ "(open)", and — because `'0'` is a non-empty string — an id deliberately closed would have read
264
+ "12 / 0". It now reads "12 / 10" and "12 (closed — no more can be minted)".
265
+ - **Projection columns**: `projects.default_max_supply`, `tokens.max_supply_overridden` (migration-added,
266
+ so an existing store keeps working; NULL stays NULL rather than becoming a fabricated `0`).
267
+
268
+ Also in this pass, from the same review:
269
+
270
+ - **`SPINE_EVENT_DOC` had drifted to 41 of 52 events**, so eleven folded events carried an empty
271
+ human description and defaulted to Register 2 — including `TransferValidatorUpdated`, which belongs
272
+ to Register 1, and the factory's `Deployed`. All eleven are described, and a new
273
+ `spine-doc-coverage.test.ts` fails the build if the table and the spine ABI drift apart again in
274
+ either direction.
275
+ - **One provenance body in the resolver's `renderer` branch.** The `text/uri-list` arm hand-built an
276
+ object byte-identical to `onChainProv(field, 'renderer', …)` — same keys, same order, the note string
277
+ typed a second time — so the only thing that branch could do was drift from `sourceNote`.
278
+ - **Dead `abx_params`-era test scaffolding deleted** (a `paramsOf(json) => json.abx_params` reader, an
279
+ RPC stub, a schema factory), including an import of a `ParamMember` type that no longer exists —
280
+ which nothing caught, because `tsconfig` includes only `src`, so test files are never typechecked.
281
+
282
+ ### Patch Changes
283
+
284
+ - Updated dependencies [7fec2d7]
285
+ - @artblocks/abx-sdk@0.1.0-alpha.15
286
+
287
+ ## 0.1.0-alpha.15
288
+
289
+ ### Patch Changes
290
+
291
+ - Updated dependencies [1b6b741]
292
+ - Updated dependencies [1b6b741]
293
+ - Updated dependencies [1b6b741]
294
+ - Updated dependencies [1b6b741]
295
+ - Updated dependencies [1b6b741]
296
+ - Updated dependencies [1b6b741]
297
+ - Updated dependencies [f64a31f]
298
+ - Updated dependencies [1b6b741]
299
+ - Updated dependencies [1b6b741]
300
+ - Updated dependencies [1b6b741]
301
+ - Updated dependencies [1b6b741]
302
+ - Updated dependencies [1b6b741]
303
+ - Updated dependencies [1b6b741]
304
+ - Updated dependencies [1b6b741]
305
+ - Updated dependencies [1b6b741]
306
+ - Updated dependencies [1b6b741]
307
+ - Updated dependencies [1b6b741]
308
+ - @artblocks/abx-sdk@0.1.0-alpha.14
309
+
310
+ ## 0.1.0-alpha.14
311
+
312
+ ### Patch Changes
313
+
314
+ - Updated dependencies [528c6c6]
315
+ - @artblocks/abx-sdk@0.1.0-alpha.13
316
+
317
+ ## 0.1.0-alpha.13
318
+
319
+ ### Minor Changes
320
+
321
+ - afa9dd4: ERC-1155 editions ship with full parity: a Series is many unique tokens (721); an **Edition** is
322
+ many copies of a token (1155). The creator's word is **copies** — `abx deploy img.png --copies 100`
323
+ (a single-artwork edition, `open` = uncapped), `abx deploy-series ./art --copies 50` (each image an
324
+ edition), `abx deploy-code sketch.js --copies 25` (code editions). Without `--copies`, the 721
325
+ lanes are unchanged.
326
+
327
+ Three new canonical contracts twin the 721 lineup — `OneOfOneEdition`, `EditionImage`,
328
+ `EditionCode` — plus `AbxFixedPriceMinter1155`, a per-id fixed-price sale singleton
329
+ (`minter configure/buy --token-id [--quantity]`). New owner ops: `mint --token-id --amount`,
330
+ `transfer --amount`, `set-max-supply` (per-id cap, only ever decreases), `ping-uri` (re-emit the
331
+ native `URI` event after a re-point). ERC-1155C creator-token enforcement is the same `--721c`
332
+ opt-in (same validator registry and ERC-165 ids as 721C). Editions announce one new extension
333
+ (`abx.extension.edition-supply`, per-id supply/cap); everything else — metadata fields, params,
334
+ royalties, renderer, storage, effects — is the same protocol surface on both standards.
335
+
336
+ **Integrator surface (audience line):** additive only. `ProjectState.contractType` gains
337
+ `'1of1-edition' | 'edition' | 'edition-code'`; `TokenState` gains `supply`/`maxSupply`/`holders`
338
+ (editions only; `minted` means supply > 0 there); the spine ABI now decodes
339
+ `TransferSingle`/`TransferBatch`/`URI`/`MaxSupplyUpdated`; `ChainDeployment` gains the four
340
+ edition anchors (recorded for Sepolia + Base Sepolia, CREATE2-identical); token-api summaries gain
341
+ an optional `copies` field. No existing export, route, column, or event shape changed.
342
+
343
+ - 8c254d5: The self-host projection no longer stores or pre-fetches composed URI documents, and the event log
344
+ is append-only (from the abx-services 2026-08-05 projection memo, `docs/11`).
345
+
346
+ - **`contractURI`/`tokenURI` are live reads, never projected.** `reconstructProject`/
347
+ `reconstructIncremental` gain `readUriDocuments` (default **false**) — with it off, the whole
348
+ `contractURI`/`tokenURI` head-read batch is skipped entirely, not fetched-and-discarded. These
349
+ fields have no settled value (a renderer can change the composed document with no log at all) and,
350
+ on the on-chain lane, can run hundreds of KB per token — a real 32-token project measured 13.4 MB
351
+ serialized, 99.8% of it `tokenURI`. A stale-but-rendering `data:` URI is worse than a missing one,
352
+ because nothing about it looks wrong. `abx demo` is the one caller that passes `readUriDocuments:
353
+ true`, for its read-back teaching step; `abx deploy`/`deploy-series`/`deploy-code` don't, and
354
+ `abx verify`/`tokenuri`/`contracturi` were already doing independent live reads. **For
355
+ integrators:** `ProjectState.contractURI` / `TokenState.tokenURI` are now `null` unless you opt in
356
+ — including in a self-host node's `/api/project/:addr` responses (shape unchanged, values now
357
+ null). Nothing that composes served metadata reads either field (the settled `fields`/
358
+ `collectionFields` do); the settled scalars — `tokenURIRenderer`/`tokenURILocked`/
359
+ `contractURIRenderer`/`contractURILocked` — are unaffected and still projected.
360
+ - **The events table is append-only.** `seq` is now chain-derived (`(blockNumber << 32) |
361
+ logIndex`, BigInt-safe) instead of the array index at write time, so it's stable across re-folds —
362
+ a re-index appends via `ON CONFLICT DO NOTHING` instead of deleting and reinserting the whole
363
+ history on every delta. `putProject` upserts the project and token rows in place (a token whose id
364
+ vanishes from state is still removed) rather than delete-and-reinsert. `deregister` still deletes
365
+ a forgotten project's events in full; a routine re-fold does not. **A full replay (`abx index
366
+ --full`) purges the project's event log before rebuilding it** — append-only must not let a
367
+ reorg-replaced event survive as a stale row, so the documented repair path stays a real repair.
368
+ Existing stores migrate their positional `seq` values to the chain-derived form once, automatically
369
+ (`PRAGMA user_version`-gated, transactional).
370
+ - **Self-healing eventCount guard.** An incremental fold that would reduce `eventCount` below what's
371
+ already stored is discarded rather than written, with one automatic full-reconstruct fallback (the
372
+ memo's own war story: a bad fold once silently zeroed a live projection with nothing to catch it).
373
+ - **New self-host stores open with `auto_vacuum = INCREMENTAL`.** Existing stores are unaffected
374
+ (the pragma only takes on a database with no tables yet) — recorded as backlog B29.
375
+
376
+ ### Patch Changes
377
+
378
+ - Updated dependencies [afa9dd4]
379
+ - Updated dependencies [8c254d5]
380
+ - @artblocks/abx-sdk@0.1.0-alpha.12
381
+
382
+ ## 0.1.0-alpha.12
383
+
384
+ ### Patch Changes
385
+
386
+ - Updated dependencies [d40caf4]
387
+ - Updated dependencies [d40caf4]
388
+ - @artblocks/abx-sdk@0.1.0-alpha.11
389
+
390
+ ## 0.1.0-alpha.11
391
+
392
+ ### Patch Changes
393
+
394
+ - Updated dependencies [11fa933]
395
+ - Updated dependencies [11fa933]
396
+ - Updated dependencies [11fa933]
397
+ - @artblocks/abx-sdk@0.1.0-alpha.10
398
+
399
+ ## 0.1.0-alpha.10
400
+
401
+ ### Patch Changes
402
+
403
+ - Updated dependencies [df298d8]
404
+ - Updated dependencies [df298d8]
405
+ - @artblocks/abx-sdk@0.1.0-alpha.9
406
+
407
+ ## 0.1.0-alpha.9
408
+
409
+ ### Patch Changes
410
+
411
+ - Updated dependencies [e325b46]
412
+ - @artblocks/abx-sdk@0.1.0-alpha.8
413
+
414
+ ## 0.1.0-alpha.8
415
+
416
+ ### Patch Changes
417
+
418
+ - Updated dependencies [1b50f9d]
419
+ - Updated dependencies [1b50f9d]
420
+ - @artblocks/abx-sdk@0.1.0-alpha.7
421
+
422
+ ## 0.1.0-alpha.7
423
+
424
+ ### Patch Changes
425
+
426
+ - Updated dependencies [1158420]
427
+ - Updated dependencies [1158420]
428
+ - Updated dependencies [1158420]
429
+ - @artblocks/abx-sdk@0.1.0-alpha.6
430
+
431
+ ## 0.1.0-alpha.6
432
+
433
+ ### Minor Changes
434
+
435
+ - feba8c2: A resolver is no longer an object store: effect outputs split into **bound** and **referenced**
436
+ (`specs/protocol/effects.md → Bound vs referenced`), and the artifact registry enforces the split.
437
+
438
+ An output is **bound** iff a binding stitches its _content_ into the metadata JSON (today exactly
439
+ `render/traits` → `attributes`); everything else is **referenced** — the projection carries its URL,
440
+ or it only appears in the `artifacts` manifest. That one distinction decides who holds the bytes, and
441
+ it is now the wire rule rather than a runner constant.
442
+
443
+ - **`POST /v1/effect-artifacts` derives the mode from the binding, and refuses both mismatches.**
444
+ Bytes for a referenced output → `400` (the resolver redirects either way, so the bytes buy no
445
+ capability and cost it storage, retention and egress). A locator for a bound output → `400` (its
446
+ content is assembled into `tokenURI`; a pointer there used to be recorded and then silently never
447
+ stitch — a wrong answer served confidently). Bound content is capped at **64 KB**, and a locator
448
+ that only the producer could resolve (loopback/private host, presigned expiring URL) is rejected.
449
+ The resolver never fetches a locator while handling the write, and serves registered locators by
450
+ `302` — never by proxying.
451
+ - **Bound content moved out of byte custody** into the artifact row (`effect_artifacts.bytes`). Two
452
+ distinct rules, deliberately not one: a node **MUST** serve and stitch bound content only at the
453
+ token's current settled `inputsHash`, and it **MAY** drop superseded content whenever it likes
454
+ (nothing may read it, and it is re-creatable). The reference drops eagerly, on each bound
455
+ registration, so it holds at most `64 KB × minted × bound outputs` — but retention is a service
456
+ policy, not an obligation. Either way "conforming means holding a bounded amount of JSON in the
457
+ database you already run" is now literally true: a resolver in the publish topology needs no object
458
+ storage at all.
459
+ - **`abx-effects-publish/v1` is gone** (not deprecated): the two routes ride `abx-control-plane/v1`.
460
+ Once referenced output is locator-only, accepting a registration is a database insert, so the
461
+ capability flag described a distinction that no longer exists. A service that won't take a caller's
462
+ artifacts refuses on the credential (`403`) — interfaces describe wire grammar, tokens describe
463
+ permission. The interface ids are also explicitly **all-or-nothing**, and the conformance fixture
464
+ now checks that every route a declared interface names actually answers.
465
+ - **The runner declares bound outputs** (`EffectOutputDecl.bound`), refuses to start when it has a
466
+ publish token but a backend that can't name a locator, preflights the descriptor + credential
467
+ before spending a render, and **latches** on a permanent (4xx) publish failure instead of
468
+ re-rendering every sweep forever. Skips now re-register rows, so a transient publish failure heals
469
+ without a re-render.
470
+ - **The CLI refuses the impossible combination up front**: `abx render --remote`, `abx effects`
471
+ against a remote resolver, and `abx deploy-effects` all require a backend that can name a reachable
472
+ URL — `cloud` (S3/R2 + public base), `ipfs`, or `arweave`, named as **peers**. Derived output is
473
+ re-creatable, so the protocol has no preference among schemes: a chosen `https://` gateway or
474
+ bucket URL is exactly as legitimate as `ipfs://`/`ar://`, and reachability — not durability — is
475
+ the requirement. Rendering **co-located** with the resolver remains fully supported on any backend,
476
+ including `fs`.
477
+
478
+ Breaking for producers that relied on pushing media bytes to a resolver: publish a locator instead,
479
+ or co-locate. Breaking for clients that read `abx-effects-publish/v1` from a descriptor.
480
+
481
+ ### Patch Changes
482
+
483
+ - Updated dependencies [feba8c2]
484
+ - @artblocks/abx-sdk@0.1.0-alpha.5
485
+
486
+ ## 0.1.0-alpha.5
487
+
488
+ ### Patch Changes
489
+
490
+ - Updated dependencies [67b686b]
491
+ - @artblocks/abx-sdk@0.1.0-alpha.4
492
+
493
+ ## 0.1.0-alpha.4
494
+
495
+ ### Minor Changes
496
+
497
+ - a72723d: A standard indexing lifecycle, and registration that no longer blocks on a slow chain RPC
498
+ (specs/self-host-toolkit/remote-services.md → The indexing lifecycle).
499
+
500
+ - **Fixed: a slow register triggered a retry storm.** The SDK's per-attempt timeout (30s) plus its
501
+ retry ladder meant a cold reconstruct that outran one request was **re-POSTed up to four times**,
502
+ each starting another full replay against the RPC that was already too slow to answer — and the
503
+ caller then saw "nothing responded" even though the registration was durable and indexing was
504
+ underway. A timed-out register now asks whether it landed (a status read) instead of re-POSTing, and
505
+ the resolver coalesces concurrent catch-ups for one project into a single run.
506
+ - **`POST /v1/projects` answers in two conformant shapes, discriminated by HTTP status:** `200` with
507
+ the completed summary, or `202` + `{accepted, project: {status}}` when catch-up is deferred. The
508
+ registration is normatively **durable before catch-up** and visible on the list immediately, so a
509
+ flaky RPC makes for a slower backfill rather than a lost add. No `?wait=`/`Prefer:` negotiation — the
510
+ status code is the discriminator, and clients handle both. The reference resolver answers _by
511
+ deadline_ (`ABX_REGISTER_DEADLINE_MS`, default 8s): the common case (a fresh deploy) stays
512
+ synchronous with real counts; only the pathological case defers.
513
+ - **Closed lifecycle enum + error classes, on the status and list routes:**
514
+ `queued | backfilling | live | stale | failed`, plus credential-free
515
+ `error.class ∈ {rpc_unavailable, rpc_rate_limited, not_abx_contract, internal}` (fixed per-class
516
+ messages, never a scrubbed upstream string). Status gains top-level `headBlock` (so lag / % complete
517
+ is computable without knowing a service has a watcher) and `attempts`; the list carries `status` +
518
+ the error class, so a client renders "3 live, 1 backfilling, 1 failed (rpc_rate_limited)" in one
519
+ request. SDK: `IndexStatus`, `IndexErrorClass`, `isAccepted()`, `indexProgress()`,
520
+ `classifyIndexError()`, and `AbxServiceClient.awaitIndexed()` — one wait loop for the CLI, the
521
+ effects runner, and any hosted agent.
522
+ - **The same five words on your own node.** `abx status [address] [--remote [name|url]] [--watch]`:
523
+ bare is the node summary (now with each project's state), an address gives lifecycle + scan floor +
524
+ blocks-indexed-vs-head + cause, and `--remote` asks a service. (`status` = who is serving it and how
525
+ fresh; `state` = what the chain says. Both `--help` texts now say so.)
526
+ - **New observability the self-hosted node never had:** the chain watcher marks projects `stale` when
527
+ it falls far behind head or its ticks keep failing (previously visible only in the node's log),
528
+ re-queues a backfill interrupted by a restart (previously left registered-but-empty until a manual
529
+ `abx index`), and retries a `failed` catch-up on exponential backoff instead of hammering a
530
+ rate-limited RPC every tick. Lifecycle rows live in their own table: they survive a projection wipe
531
+ and are never clobbered by a re-add.
532
+ - **CLI:** `abx add|index --remote` prints `registered — backfilling…`, polls to `live`, then prints
533
+ the same summary a synchronous service would have given; `--no-wait` returns at the 202 and names
534
+ the command to check later. A post-op nudge (`ownerops`) never blocks on someone else's backfill.
535
+ A caught-up project with **0 events** now warns instead of printing ✓ (a real ABX clone always emits
536
+ a spine, so zero means wrong chain/floor or an RPC that didn't serve the logs).
537
+ - **Conformance fixture** accepts either register shape, asserts durable-before-catch-up, lifecycle
538
+ membership, `headBlock`, that a deferred catch-up actually reaches `live`, and that no error message
539
+ carries a URL.
540
+ - Fixed `scripts/mock-remote-service.mts`, which imported the token API by a path that resolved
541
+ against `scripts/` and could silently fall back to a _published_ build outside the repo — the
542
+ fixture was testing the last release instead of the working tree. The fixture also re-points
543
+ scenarios by their fixture header now, so a new one can't keep a dead contract address.
544
+
545
+ Found by a cold-agent sweep over the above (10 parallel clean rooms, haiku + sonnet) and fixed here:
546
+
547
+ - **`abx status --remote <name>` with no address** parsed the flag itself as the address and sent it
548
+ as a URL path segment.
549
+ - **A register whose catch-up already failed** was announced as "registered — failed (…is catching
550
+ up…)", and with `--no-wait` it exited 0 and then claimed the provider "now serves" the project. A
551
+ known failure is now an error in both lanes — there is nothing left to wait for.
552
+ - **A `failed` status said what broke but not whose problem it was.** Both the failure error and
553
+ `abx status` now carry a per-class action line ("the SERVICE can't reach its chain RPC — not your
554
+ key, address, or chain…"), plus a `follow` line naming `--watch`, so a red word isn't a dead end.
555
+ - **A `live` project showed a misleading completion percentage.** `toBlock` only advances when a
556
+ project has _events_, so a fully current project on a busy chain read as `2/202 (0%)`.
557
+ `indexProgress()` now returns a ratio only while `backfilling`; `live` reads "caught up", `stale`
558
+ reads "not tracking head right now".
559
+ - **`--remote-token` was misattributed on a 401** — the error blamed `ABX_REMOTE_<NAME>_TOKEN` even
560
+ when the caller passed an override, making the override look ignored at exactly the moment someone
561
+ is testing a replacement key.
562
+ - **`not_registered` on a read** (status/reindex) now names the register command instead of echoing a
563
+ 404, and a 5xx carrying a failure `class` becomes a wait-vs-broken error.
564
+ - **`abx verify`'s summary** read `✓ 0/1 up to date` for a project with no off-chain renders at all —
565
+ "zero of one succeeded" to two independent reviewers. It now says "nothing to render for this
566
+ project", and otherwise leads with polarity ("N of M token(s) current").
567
+ - **`abx doctor` now reports named remotes** and flags a credential stored under a name the CLI does
568
+ not read (`ABX_REMOTE_<NAME>_KEY`). That fault presents as "it acts like I never gave it a key" and
569
+ previously only surfaced from `abx remote <name>` — which a creator reaches _after_ doctor.
570
+ - **Skill: the `npx --no-install abx version` probe was documented as failing cleanly.** It doesn't —
571
+ npm will run any `abx` binary already in the npx cache, which in a real sweep reported a months-old
572
+ build as the project's CLI (and if a plain `npx abx` ever ran on that machine, the bare name is a
573
+ squatted package). The skill now probes `./node_modules/.bin/abx` directly.
574
+ - Also documented: how a multi-word provider name folds into `ABX_REMOTE_<NAME>_*`, and what
575
+ `watching: no` means on a status readout.
576
+
577
+ A second sweep round over those fixes caught three more, including one the first round's fix created:
578
+
579
+ - **`abx verify --remote` never checked byte integrity at all** — both of its lanes only ask "is there
580
+ a current render / is this a placeholder", and a green ✓ from that was standing in for "the served
581
+ bytes match the on-chain commitment". A reviewer hit the worst version of this: `--remote` (the form
582
+ the skill tells you to use for a hosted project) reported ✓ on a token whose bytes genuinely did NOT
583
+ hash-match, while bare `abx verify` on the same project reported `✗ keccak256 MISMATCH`. It now calls
584
+ the service's own purpose-built `GET /api/project/:addr/verify` (which holds both the bytes and the
585
+ chain) and reports that verdict separately from the render summary — and when it _can't_ run that
586
+ check (no credential, older node) it says "byte integrity NOT checked" instead of leaving a ✓ to
587
+ imply it passed. The remedy names both real causes (an unbridged durable locator vs. bytes that only
588
+ exist on the creator's machine, which a hosted resolver can never serve).
589
+ - **`abx verify` exited 0 while printing a byte MISMATCH**, in both lanes — nothing could gate on it.
590
+ An integrity mismatch now fails the command; a missing render or placeholder is a normal state and
591
+ still exits 0.
592
+ - **`abx add --dry-run` silently ignored the flag and performed the registration**, local or remote.
593
+ It now refuses and names the read-only commands (`abx state`, `abx status`) instead. Silently doing
594
+ the thing when the caller asked to preview is the one outcome that must never happen.
595
+ - **`PRAGMA busy_timeout` was set third in the store schema**, after the WAL switch it needs to
596
+ protect — so two processes opening the same store at once (parallel CLI runs, or a co-located
597
+ effects runner starting alongside the resolver) could fail outright with `database is locked`
598
+ instead of waiting the moment out. It is now the first statement.
599
+
600
+ A third round, re-running the scenario that found the verify bug (it now catches it) turned up:
601
+
602
+ - **`abx add --remote` ended on "it now serves <url>"** — true about indexing, silent about whether
603
+ the bytes are right, and two reviewers stopped there and reported a blank page as fixed. It now names
604
+ the byte check (`abx verify <addr> --remote <name>`) in the same breath.
605
+ - **`canonical:` collapsed a tri-state.** `isCanonical` is `true | false | null`, and both readouts
606
+ printed "unverified" for the last two — so "the chain says this is NOT a clone of the configured
607
+ factory" (a trust finding) looked identical to "the check never ran" (no factory on this chain, normal
608
+ on a dev chain). Two reviewers read the collapsed word as a second failure sitting next to a real one.
609
+ - **`abx verify --remote` gave a bare `fetch failed`** for an endpoint that was down, where
610
+ `abx status --remote` names the host and asks whether it's running. Two commands, one condition, two
611
+ error qualities — now consistent.
612
+ - `abx status <addr>` printed the address twice when the project has no name.
613
+ - Skill: registering with a provider on **their** hostname vs. a domain you control decides whether
614
+ leaving later costs a transaction — now stated in the managed-provider section, before you bake it.
615
+
616
+ ### Patch Changes
617
+
618
+ - Updated dependencies [a72723d]
619
+ - @artblocks/abx-sdk@0.1.0-alpha.3
620
+
621
+ ## 0.1.0-alpha.3
622
+
623
+ ### Patch Changes
624
+
625
+ - Updated dependencies [3745bd3]
626
+ - Updated dependencies [3745bd3]
627
+ - @artblocks/abx-sdk@0.1.0-alpha.2
628
+
629
+ ## 0.1.0-alpha.2
630
+
631
+ ### Patch Changes
632
+
633
+ - Updated dependencies [4074766]
634
+ - @artblocks/abx-sdk@0.1.0-alpha.1
635
+
636
+ ## 0.1.0-alpha.1
637
+
638
+ ### Patch Changes
639
+
640
+ - c21ea30: Publish the `dropProjection` API that `abx demo` depends on. `dropProjection` was added to the
641
+ indexer and called from the CLI's demo in the same commit, but no changeset bumped
642
+ `@artblocks/abx-indexer` — so it was never republished, and the CLI published at `0.1.0-alpha.5`
643
+ pinned `@artblocks/abx-indexer@0.1.0-alpha.0`, which has no such method. Installing from npm and
644
+ running `abx demo` therefore died at step [4] with `indexer.dropProjection is not a function`. In-repo
645
+ runs never saw it because `workspace:*` resolves to source, where the method exists.
package/dist/index.d.ts CHANGED
@@ -4,6 +4,6 @@
4
4
  * Replays the event spine from chain into a disposable, rebuildable projection.
5
5
  * The canonical re-index: how every service onboards or exits a project.
6
6
  */
7
- export { SelfHostIndexer, type IndexResult } from './indexer.js';
7
+ export { SelfHostIndexer, type IndexResult, type ReindexOptions } from './indexer.js';
8
8
  export { SqliteStore, type Store, type ProjectRegistration, type EffectStatusRow, type EffectArtifactRow, } from './store.js';
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAE,KAAK,WAAW,EAAC,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,WAAW,EACX,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAC,MAAM,cAAc,CAAC;AACpF,OAAO,EACL,WAAW,EACX,KAAK,KAAK,EACV,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAmB,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,WAAW,GAKZ,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAC,eAAe,EAAwC,MAAM,cAAc,CAAC;AACpF,OAAO,EACL,WAAW,GAKZ,MAAM,YAAY,CAAC"}