arkiv-images 1.0.2 → 1.0.3

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/AGENTS.md CHANGED
@@ -2,7 +2,7 @@ Edit instructions only in AGENTS.md; CLAUDE.md only imports this file.
2
2
 
3
3
  # Integrating arkiv-images
4
4
 
5
- Read [README.md](README.md) explicitly for the public API, runnable local example, data model, limits, signing and recovery. Install version 1.0.2 with `npm install arkiv-images@1.0.2 @arkiv-network/sdk@1.0.0 viem@2.56.3`.
5
+ Read [README.md](README.md) explicitly for the public API, runnable local example, data model, limits, signing and recovery. Install version 1.0.3 with `npm install arkiv-images@1.0.3 @arkiv-network/sdk@1.0.0 viem@2.56.3`.
6
6
 
7
7
  - Ask whether the task needs local inspection, retrieval or a new public upload. Inspection requires no network. Retrieval needs an image key, Rabdi and optionally an independently trusted SHA-256. Writes additionally require a locally configured signing wallet and test funds.
8
8
  - Ask whether original bytes, filename and metadata are safe to publish. EXIF/GPS is preserved. Stop if confidentiality is required; encryption is a different tool.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.3
4
+
5
+ - Depends on arkiv-chunking 1.1.2 for the corrected shared write policy, which preserves an uncertain submission hash without resending.
6
+
3
7
  ## 1.0.2
4
8
 
5
9
  - Use the long-lived JPEG example, filter expired examples by current block, align VERSION guidance and verify archives using package.json.
package/README.md CHANGED
@@ -2,18 +2,18 @@
2
2
 
3
3
  Store a public PNG or JPEG as queryable Arkiv entities, then retrieve its original bytes with size, MIME, dimensions and SHA-256 checks. Small images use one entity with a non-indexed `bytes()` column. Larger images use `arkiv-chunking`: an image entity references a file manifest and ordered immutable chunks.
4
4
 
5
- **arkiv-images 1.0.2 targets Rabdi testnet.** It stores PNG/JPEG binary data in `bytes` columns. See [verification](docs/verification.md) for reproducible checks and separately labelled historical observations.
5
+ **arkiv-images 1.0.3 targets Rabdi testnet.** It stores PNG/JPEG binary data in `bytes` columns. See [verification](docs/verification.md) for reproducible checks and separately labelled historical observations.
6
6
 
7
7
  ## Install and inspect
8
8
 
9
- ESM, Node 22.10+ with Web Crypto, or a browser on HTTPS/localhost. Tested dependencies: SDK 1.0.0, viem 2.56.3, arkiv-chunking 1.1.0.
9
+ ESM, Node 22.10+ with Web Crypto, or a browser on HTTPS/localhost. Tested dependencies: SDK 1.0.0, viem 2.56.3, arkiv-chunking 1.1.2.
10
10
 
11
11
  ```sh
12
12
  mkdir image-consumer
13
13
  cd image-consumer
14
14
  npm init -y
15
15
  npm pkg set type=module
16
- npm install arkiv-images@1.0.2 @arkiv-network/sdk@1.0.0 viem@2.56.3
16
+ npm install arkiv-images@1.0.3 @arkiv-network/sdk@1.0.0 viem@2.56.3
17
17
  ```
18
18
 
19
19
  Save `inspect.mjs`:
@@ -76,7 +76,7 @@ Run `node roundtrip.mjs` after configuring those environment variables locally.
76
76
  | `ImageSchema`, `IMAGE_TYPE` | SDK 1.0 named schema `arkiv-images/v2`. Binary `data` is stored without an index. Indexed type/mode/mime/sha256/manifest support discovery. Filename, size and dimensions are stored typed columns. |
77
77
  | `ImageStorageError`, `ChunkingError` | Safe code/message; preserve imageKey/manifestKey and transactionHashes on failure. Raw causes can include provider details: never display or log them. |
78
78
  | `TransactionParameterPolicy`, `Progress` | Public TypeScript integration types re-exported from chunking. |
79
- | `VERSION`, `INLINE_MAX_BYTES`, `MAX_IMAGE_BYTES`, `MAX_IMAGE_PIXELS`, `MAX_EXPIRATION_BLOCKS`, `RABDI_MAX_LIFETIME_BLOCKS`, `EXPIRATION_INCLUSION_MARGIN_BLOCKS` | Implementation version (`1.0.2`) and enforced limits. |
79
+ | `VERSION`, `INLINE_MAX_BYTES`, `MAX_IMAGE_BYTES`, `MAX_IMAGE_PIXELS`, `MAX_EXPIRATION_BLOCKS`, `RABDI_MAX_LIFETIME_BLOCKS`, `EXPIRATION_INCLUSION_MARGIN_BLOCKS` | Implementation version (`1.0.3`) and enforced limits. |
80
80
 
81
81
  Import types such as `ImageInfo`, `ImagePlan`, `StoreImageOptions`, `StoredImage`, `RetrieveImageOptions`, `RetrievedImage`, `ImageContentType` and `ImageErrorCode` directly from `arkiv-images`.
82
82
 
@@ -88,7 +88,7 @@ Entity Expiration is whole blocks, at least `max(64, transactionCount + 32)` and
88
88
 
89
89
  Every part and the final root reuse the public `arkiv-chunking` write policy: an unsigned SDK request is estimated at `latest`; gas is at least `max(1_000_000, 2 × estimate)`, with explicit network gasPrice and a fresh latest nonce. The image API additionally stops before signing if that budget exceeds half the latest block gas limit. Longer expiration can substantially increase gas, so shorten Entity Expiration or choose a smaller image if the estimate exceeds that budget. Admitted byte/lifetime limits do not guarantee every combination fits the network's gas budget. `txParams` can increase gas or change fees; it cannot remove required headroom or override the latest nonce. Wallet account/network are checked before every signature.
90
90
 
91
- Serialize writes from the same account. A retry is permitted only once after an authoritative gas-exhausted reverted receipt and only within the half-block gas ceiling. Successful or uncertain writes are never automatically resent. `CONFIRMATION_PENDING` preserves SDK-success hashes and root/manifest keys if a later receipt lookup is unresolved or disagrees. The operation enters `submitted` before that lookup. Browser consumers must keep a `createImageWriteOperation` object across renders and later clicks; `storeImage` is a one-call convenience for an intentional new upload. Inspect preserved receipts before explicitly creating another operation. The sample resets the operation only when you choose a file again. Other failures can also leave confirmed entities. There is no multi-transaction atomicity, rollback, resumable upload, independent part mutation/transfer/extension or automatic cleanup.
91
+ Serialize writes from the same account. A retry is permitted only once after an authoritative gas-exhausted reverted receipt and only within the half-block gas ceiling. Successful or uncertain writes are never automatically resent. `CONFIRMATION_PENDING` preserves a known submission hash, including one recovered by the shared policy from a wrapped SDK error, plus any available root/manifest keys. SDK-success results enter `submitted` before the receipt recheck; a known-hash SDK error enters `submitted` when the shared policy returns its unresolved confirmation. Observed hashes are recovery evidence, not proof of successful receipts. Browser consumers must keep a `createImageWriteOperation` object across renders and later clicks; `storeImage` is a one-call convenience for an intentional new upload. Inspect preserved receipts before explicitly creating another operation. The sample resets the operation only when you choose a file again. Other failures can also leave confirmed entities. There is no multi-transaction atomicity, rollback, resumable upload, independent part mutation/transfer/extension or automatic cleanup.
92
92
 
93
93
  Retrieval uses latest-state keyset pages and verifies immutable chunks, owner/creator, sequence, lengths, metadata and digest; the manifest is rechecked before return. It does not claim a historical snapshot. An independently trusted digest pins bytes, not the publisher's identity. Missing/corrupt chunks never return a partial image.
94
94
 
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type Column, type Schema, type TypeTag } from '@arkiv-network/sdk/schema';
2
2
  import { type TransactionParameterPolicy, type ChunkingPublicClient, type ChunkingWalletClient, type Progress } from 'arkiv-chunking';
3
3
  import { type Hex } from 'viem';
4
- export declare const VERSION = "1.0.2";
4
+ export declare const VERSION = "1.0.3";
5
5
  export declare const IMAGE_TYPE = "arkiv-images/v2";
6
6
  type Stored<T extends TypeTag> = Column<T, false, false, false>;
7
7
  type Indexed<T extends TypeTag> = Column<T, true, false, false>;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { bytes as binary, defineSchema, key, str, u64 } from '@arkiv-network/sdk
3
3
  import { eq } from '@arkiv-network/sdk/query';
4
4
  import { uploadFile, downloadFile, hashFile, ChunkingError, DEFAULT_CHUNK_BYTES, MAX_EXPIRATION_BLOCKS, writeWithPolicy, WriteConfirmationPendingError } from 'arkiv-chunking';
5
5
  import { hexToBytes } from 'viem';
6
- export const VERSION = '1.0.2';
6
+ export const VERSION = '1.0.3';
7
7
  export const IMAGE_TYPE = 'arkiv-images/v2';
8
8
  export const ImageSchema = defineSchema(IMAGE_TYPE, {
9
9
  type: str().indexed(), mode: str().indexed(), mime: str().indexed(), sha256: str().indexed(),
@@ -234,6 +234,12 @@ async function executeStoreImage(options, submitted, observed) {
234
234
  return { ...info, imageKey: stored.entityKey, manifestKey, mode: plan.mode, sha256, transactionHashes };
235
235
  }
236
236
  catch (cause) {
237
+ // The shared policy can recover a submission hash from a wrapped SDK error.
238
+ // Retain that typed pending evidence without treating it as a successful receipt.
239
+ if (cause instanceof WriteConfirmationPendingError || (cause instanceof ChunkingError && cause.code === 'CONFIRMATION_PENDING')) {
240
+ if (hex32(cause.txHash))
241
+ rememberHash(cause.txHash);
242
+ }
237
243
  if (cause instanceof ChunkingError) {
238
244
  manifestKey = cause.manifestKey ?? manifestKey;
239
245
  cause.transactionHashes.forEach(rememberHash);
@@ -241,7 +247,7 @@ async function executeStoreImage(options, submitted, observed) {
241
247
  if (cause instanceof ImageStorageError && !transactionHashes.length)
242
248
  throw cause;
243
249
  const pending = cause instanceof WriteConfirmationPendingError || (cause instanceof ChunkingError && cause.code === 'CONFIRMATION_PENDING');
244
- throw new ImageStorageError(pending ? 'CONFIRMATION_PENDING' : 'UPLOAD_FAILED', pending ? 'The SDK reported a successful write, but receipt confirmation is pending. Preserve the image/manifest keys and hashes; inspect them using reads and never resend automatically.' : 'Upload did not complete. Inspect the wallet and available transaction receipts before retrying; any previously written entities remain.', { cause, manifestKey, imageKey, transactionHashes });
250
+ throw new ImageStorageError(pending ? 'CONFIRMATION_PENDING' : 'UPLOAD_FAILED', pending ? 'A submitted write has unresolved receipt confirmation. Preserve the image/manifest keys and hashes; inspect them using reads and never resend automatically.' : 'Upload did not complete. Inspect the wallet and available transaction receipts before retrying; any previously written entities remain.', { cause, manifestKey, imageKey, transactionHashes });
245
251
  }
246
252
  }
247
253
  function attr(attributes, name, type) {
@@ -1,4 +1,4 @@
1
- # Verify arkiv-images 1.0.2
1
+ # Verify arkiv-images 1.0.3
2
2
 
3
3
  Use Node 22.10+ on the DGX. From this checkout run `npm ci --no-audit --no-fund`, then `node scripts/verify-candidate.mjs`. The script reads package.json, runs library gates, packs that exact version, installs it in a private clean consumer, checks runtime VERSION and public TypeScript imports, and builds an isolated copy of the sample using the same archive. It preserves the sample registry pin and lockfile.
4
4
 
@@ -6,7 +6,7 @@ To check a registry installation of the same version, run `node scripts/verify-c
6
6
 
7
7
  The public example selects the longer-lived inline JPEG `0x2989bda8bbadfe7e22a0b1e3a435aa3b266106adbbca3f97c162ee4eccca8488` and filters entries using the current block. The short-lived PNG and chunked examples in the old measurements have expired; those measurements are not an availability promise.
8
8
 
9
- > Historical 1.0.0 measurements and procedure below are preserved from 51f4905; use the current procedure above for 1.0.2.
9
+ > Historical 1.0.0 measurements and procedure below are preserved from 51f4905; use the current procedure above for 1.0.3.
10
10
 
11
11
  # Rabdi release verification
12
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkiv-images",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Store public PNG and JPEG images as Arkiv entities and retrieve verified original bytes.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -41,7 +41,7 @@
41
41
  "prepack": "npm run build"
42
42
  },
43
43
  "dependencies": {
44
- "arkiv-chunking": "1.1.0"
44
+ "arkiv-chunking": "1.1.2"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@arkiv-network/sdk": "^1.0.0",