@totemsdk/raster-proof 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Totem SDK Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,383 @@
1
+ # @totemsdk/raster-proof
2
+
3
+ Edge-capable raster and visual evidence proof primitives for Totem Edge — asset hashes, tile Merkle roots, raster manifests, derived-layer provenance, and proof envelope integration.
4
+
5
+ No network. No storage. No GDAL. No GeoTIFF parsing. No ML. Pure hashing, manifest, provenance, and proof primitives that run safely on a drone, ship, robot, vehicle, site camera, field laptop, or edge gateway.
6
+
7
+ ## Mission
8
+
9
+ `@totemsdk/raster-proof` lets drones, robots, ships, vehicles, site cameras, satellites, field laptops, and edge gateways create verifiable proof records for imagery and raster-like data:
10
+
11
+ - drone photos
12
+ - video segments
13
+ - satellite scene windows
14
+ - GeoTIFF / COG references
15
+ - map tiles
16
+ - orthomosaic outputs
17
+ - thermal images
18
+ - lidar-derived rasters
19
+ - robot camera frames
20
+ - ship radar snapshots
21
+ - flood masks
22
+ - vegetation masks
23
+ - change-detection masks
24
+ - construction progress images
25
+ - derived analysis layers
26
+
27
+ It is **not ZEDD-specific**. ZEDD Satellite is only one application.
28
+
29
+ ### What this package does
30
+
31
+ ```text
32
+ asset metadata
33
+ + byte/content hash
34
+ + optional chunk Merkle root
35
+ + optional tile/window proof
36
+ + spatial metadata
37
+ + provenance
38
+ + signed proof envelope
39
+ + proofgraph linkage
40
+ ```
41
+
42
+ ### What this package does NOT do
43
+
44
+ ```text
45
+ ✗ GDAL
46
+ ✗ full GeoTIFF parsing
47
+ ✗ satellite provider APIs
48
+ ✗ STAC search
49
+ ✗ cloud masking
50
+ ✗ NDVI calculation
51
+ ✗ ML segmentation
52
+ ✗ orthomosaic generation
53
+ ✗ image tile server
54
+ ✗ map renderer
55
+ ✗ file-system storage
56
+ ✗ network storage
57
+ ```
58
+
59
+ Heavy processing belongs elsewhere. This package only hashes bytes and records the metadata that makes them verifiable.
60
+
61
+ ## Important wording
62
+
63
+ > This package proves bytes, manifests, provenance, windows and declared relationships. It does **not** prove that a visual interpretation is correct unless a reviewer or downstream model proof says so.
64
+
65
+ A `RasterManifest` and its proof say: "these bytes, captured by this device/operator/mission, at this time, with this content hash / Merkle root, in this spatial context". They do not claim "this water mask is correct". Interpretation correctness is a separate, explicit claim.
66
+
67
+ ## Edge-safe design
68
+
69
+ - **On a small device:** hash bytes, create manifests, sign capture records, verify Merkle proofs.
70
+ - **On a stronger edge node:** verify derived-layer provenance, evaluate spatial relations, build proof graphs.
71
+ - SHA3-256 only (from `@totemsdk/core`). No WASM gate, no Node crypto dependency, no heavy GIS imports. Deterministic everywhere — identical input always produces identical IDs, hashes, and proof IDs.
72
+
73
+ ## Installation
74
+
75
+ ```bash
76
+ npm install @totemsdk/raster-proof
77
+ ```
78
+
79
+ ## Package scope
80
+
81
+ - Byte / string hashing (`hashBytes`, `hashString`)
82
+ - Edge-safe Merkle chunking (default 64 KiB), root, inclusion proofs (domain-separated `totem-raster-leaf` / `totem-raster-node`)
83
+ - Deterministic raster manifests (`totem:raster:<sha3-256-hex>`) with asset, spatial, and provenance metadata
84
+ - Manifest validation with structured errors/warnings
85
+ - Window / tile proofs (`totem:raster-window:<sha3-256-hex>`)
86
+ - Derived-raster provenance (`createDerivedRasterManifest`, `verifyRasterDerivation`)
87
+ - `@totemsdk/proof` evidence refs, unsigned proof creation, WOTS signing, end-to-end verification
88
+ - `@totemsdk/spatial-proof` integration (raster footprint → spatial object, spatial relations)
89
+ - `@totemsdk/proofgraph` node/edge helpers
90
+
91
+ ### Dependencies
92
+
93
+ Only what is imported: `@totemsdk/core` (SHA3-256), `@totemsdk/proof` (envelopes), `@totemsdk/proofgraph` (graph helpers), `@totemsdk/spatial-proof` (relations).
94
+
95
+ ## Merkle chunking
96
+
97
+ - Default chunk size **64 KiB**; empty bytes are rejected; chunk size must be positive.
98
+ - Chunk content hash = SHA3-256 of the raw bytes. Merkle leaves and internal nodes are domain-separated, so a chunk hash can never be confused with a node hash.
99
+ - **Odd-layer rule (deterministic):** when a Merkle level has an odd number of hashes, the last hash is **promoted** unchanged to the next level (it is NOT duplicated or hashed with itself).
100
+ - All hashes are lowercase hex without `0x`.
101
+
102
+ ```typescript
103
+ import { chunkBytes, computeMerkleRoot, createRasterMerkleSummary } from '@totemsdk/raster-proof';
104
+
105
+ const bytes = new TextEncoder().encode('drone photo bytes…');
106
+
107
+ const summary = createRasterMerkleSummary(bytes, { chunkSizeBytes: 64 * 1024 });
108
+ // { contentHash, merkleRoot, chunkSizeBytes, chunkCount, byteSize }
109
+ ```
110
+
111
+ ## IDs and hashing
112
+
113
+ | ID / hash | Shape | Stable fields exclude |
114
+ |-----------|-------|----------------------|
115
+ | `rasterId` | `totem:raster:<sha3-256-hex>` | `rasterId`, `metadata` |
116
+ | `windowProofId` | `totem:raster-window:<sha3-256-hex>` | `windowProofId`, `metadata` |
117
+
118
+ ## API table
119
+
120
+ ### Hashing
121
+
122
+ | Export | Description |
123
+ |--------|-------------|
124
+ | `hashBytes(bytes)` | SHA3-256 of raw bytes → lowercase hex |
125
+ | `hashString(value)` | SHA3-256 of a UTF-8 string → lowercase hex |
126
+ | `hashSubarray(bytes, offset, length)` | Hash a byte window in place |
127
+
128
+ ### Merkle
129
+
130
+ | Export | Description |
131
+ |--------|-------------|
132
+ | `DEFAULT_CHUNK_SIZE_BYTES` | 64 KiB |
133
+ | `chunkBytes(bytes, chunkSizeBytes?)` | Split into content-hashed chunks |
134
+ | `merkleLeafHash(chunk)` | Domain-separated leaf hash of a chunk |
135
+ | `computeMerkleRoot(chunks)` | Deterministic root (promote odd last hash) |
136
+ | `createMerkleProof(chunks, leafIndex)` | Inclusion proof with siblings |
137
+ | `verifyMerkleProof(proof)` | Recompute root from leaf + siblings |
138
+ | `createRasterMerkleSummary(bytes, options?)` | Hash + chunk + root in one pass |
139
+
140
+ ### Manifests
141
+
142
+ | Export | Description |
143
+ |--------|-------------|
144
+ | `createRasterManifest(params)` | Deterministic manifest with computed `rasterId` |
145
+ | `validateRasterManifest(manifest)` | Structured validation (errors + warnings) |
146
+ | `rasterManifestToEvidenceRef(manifest)` | Manifest → `EvidenceRef` |
147
+
148
+ ### Derived provenance
149
+
150
+ | Export | Description |
151
+ |--------|-------------|
152
+ | `createDerivedRasterManifest(params)` | Derived manifest from source rasters |
153
+ | `verifyRasterDerivation(manifest, sources)` | Check declared provenance structure |
154
+
155
+ ### Window proofs
156
+
157
+ | Export | Description |
158
+ |--------|-------------|
159
+ | `createRasterWindowProof(params)` | Deterministic window proof |
160
+ | `rasterWindowProofToEvidenceRef(proof)` | Window proof → `EvidenceRef` |
161
+
162
+ ### Spatial-proof integration
163
+
164
+ | Export | Description |
165
+ |--------|-------------|
166
+ | `rasterFootprintToSpatialObject(manifest)` | Bounds → `SpatialObject`, or `null` with no bounds |
167
+ | `createRasterSpatialRelation(params)` | Raster footprint vs spatial object relation claim |
168
+
169
+ ### Proof integration
170
+
171
+ | Export | Description |
172
+ |--------|-------------|
173
+ | `rasterEvidenceRefs(manifest, windowProof?, spatialObjectId?)` | Full evidence list for a raster proof |
174
+ | `createUnsignedRasterProof(params)` | Build an unsigned `attestation` proof |
175
+ | `signRasterProof(unsigned, seed, keyIndex)` | WOTS-sign the proof |
176
+ | `verifyRasterProof(signed)` | End-to-end verification with structured reasons |
177
+
178
+ ### Proofgraph integration
179
+
180
+ | Export | Description |
181
+ |--------|-------------|
182
+ | `rasterManifestToProofGraphNode(manifest)` | Manifest → `custom` node |
183
+ | `rasterWindowProofToProofGraphNode(proof)` | Window proof → `custom` node |
184
+ | `rasterManifestToGraphEdges(manifest)` | `derived_from` / `references` / `about` edges |
185
+ | `rasterWindowProofToGraphEdges(proof)` | Window proof `derived_from` raster edge |
186
+ | `addRasterManifestToGraph(graph, manifest)` | Immutably add a manifest node |
187
+
188
+ ## Drone example
189
+
190
+ ```typescript
191
+ import {
192
+ createRasterMerkleSummary,
193
+ createRasterManifest,
194
+ createUnsignedRasterProof,
195
+ signRasterProof,
196
+ verifyRasterProof,
197
+ } from '@totemsdk/raster-proof';
198
+
199
+ const photoBytes = new TextEncoder().encode('JPEG bytes…');
200
+ const summary = createRasterMerkleSummary(photoBytes);
201
+
202
+ const manifest = createRasterManifest({
203
+ sourceType: 'drone',
204
+ layerType: 'rgb',
205
+ capturedAt: 1_712_000_000_000,
206
+ deviceId: 'drone-007',
207
+ missionId: 'mission-42',
208
+ asset: {
209
+ uri: 'https://cdn.example/flights/drone-007/ortho-001.tif',
210
+ mediaType: 'image/tiff',
211
+ format: 'geotiff',
212
+ byteSize: photoBytes.length,
213
+ contentHash: summary.contentHash,
214
+ hashAlgorithm: 'sha3-256',
215
+ merkleRoot: summary.merkleRoot,
216
+ chunkSizeBytes: summary.chunkSizeBytes,
217
+ },
218
+ spatial: {
219
+ crs: 'EPSG:4326',
220
+ bounds: [36.78, -1.29, 36.82, -1.25], // minLon, minLat, maxLon, maxLat
221
+ widthPx: 8192,
222
+ heightPx: 6144,
223
+ resolutionM: 0.05,
224
+ },
225
+ });
226
+
227
+ const unsigned = createUnsignedRasterProof({ manifest, issuer: 'drone-007', issuedAt: 1_712_000_000_000 });
228
+ const signed = signRasterProof(unsigned, seedBytes, 9); // reserve the WOTS key index first!
229
+
230
+ const result = verifyRasterProof(signed);
231
+ console.log(result.valid, result.rasterId);
232
+ ```
233
+
234
+ ## Satellite scene window example
235
+
236
+ ```typescript
237
+ import { chunkBytes, createMerkleProof, createRasterWindowProof } from '@totemsdk/raster-proof';
238
+
239
+ // A strong node chunks the full scene; a small device only needs its window.
240
+ const chunks = chunkBytes(sceneBytes, 64 * 1024);
241
+ const windowProof = createRasterWindowProof({
242
+ rasterId: manifest.rasterId,
243
+ merkleRoot: manifest.asset.merkleRoot!,
244
+ chunkIndices: [12, 13, 14],
245
+ chunkHashes: [chunks[12].hash, chunks[13].hash, chunks[14].hash],
246
+ spatial: { bounds: [36.79, -1.28, 36.80, -1.27] },
247
+ });
248
+
249
+ // Optional: carry the full leaf proofs so a verifier can recompute the root
250
+ // from the window's own bytes.
251
+ createUnsignedRasterProof({
252
+ manifest,
253
+ windowProof,
254
+ merkleProofs: [13].map((i) => createMerkleProof(chunks, i)),
255
+ issuedAt,
256
+ });
257
+ ```
258
+
259
+ ## Derived water-mask / change-mask example
260
+
261
+ ```typescript
262
+ import { createDerivedRasterManifest, verifyRasterDerivation } from '@totemsdk/raster-proof';
263
+
264
+ const waterMask = createDerivedRasterManifest({
265
+ sourceManifests: [sceneManifest], // satellite scene → water mask
266
+ layerType: 'water-mask',
267
+ asset: maskAsset,
268
+ pipelineId: 'flood-watermask-v2',
269
+ parametersHash: 'sha3-256:ab12…', // required when pipelineId is set
270
+ uncertainty: ['Model output; manual review recommended near edges.'],
271
+ spatial: sceneManifest.spatial,
272
+ });
273
+
274
+ const result = verifyRasterDerivation(waterMask, [sceneManifest]);
275
+ if (!result.valid) {
276
+ console.log(result.reasons); // e.g. missing source rasters
277
+ }
278
+ console.log(result.uncertainty); // uncertainty is preserved
279
+ ```
280
+
281
+ `verifyRasterDerivation` only verifies the **declared** provenance structure — that every `derivedFrom` ID is supplied, parameters are present when a pipeline is named, and the manifest is honestly marked `sourceType: 'derived'`. It does not verify that image processing was correct.
282
+
283
+ ## Manifest validation
284
+
285
+ `validateRasterManifest` checks:
286
+
287
+ - `sourceType`, `layerType`, `asset.format`, `asset.contentHash` required
288
+ - `asset.hashAlgorithm` must be `sha3-256`
289
+ - `createdAt` positive; `byteSize` non-negative
290
+ - `capturedAt` far after `createdAt` is rejected unless `metadata.allowFutureCapture === true`
291
+ - `spatial.bounds` in `[minLon, minLat, maxLon, maxLat]` GeoJSON order with valid ranges/ordering
292
+ - `widthPx` / `heightPx` positive integers, `resolutionM` positive
293
+ - derived rasters without `provenance.derivedFrom` produce a warning
294
+
295
+ ## Proof verification
296
+
297
+ `verifyRasterProof` checks, in order:
298
+
299
+ 1. underlying `@totemsdk/proof` verification (signature, `proofId`, expiry)
300
+ 2. payload contains a structurally valid `RasterManifest`
301
+ 3. `rasterId` recomputes from stable fields
302
+ 4. manifest evidence hash matches the payload manifest
303
+ 5. content hash and Merkle root evidence refs present when declared
304
+ 6. window proof (when supplied): `windowProofId` recomputes, root matches the manifest's root, and any supplied Merkle proofs verify and reference referenced leaves
305
+ 7. derivation structure valid for `sourceType: 'derived'`
306
+
307
+ Anchoring is not required. Source rasters are not embedded in the proof, so derivation is checked structurally inside the envelope; full cross-source verification is `verifyRasterDerivation`.
308
+
309
+ ## Spatial-proof integration example
310
+
311
+ ```typescript
312
+ import { computeSpatialObjectId } from '@totemsdk/spatial-proof';
313
+ import { rasterFootprintToSpatialObject, createRasterSpatialRelation } from '@totemsdk/raster-proof';
314
+
315
+ const site = {
316
+ spatialId: computeSpatialObjectId({
317
+ kind: 'site-boundary',
318
+ name: 'ZEDD flood site A',
319
+ geometry: { type: 'Polygon', coordinates: [[[36.78, -1.29], [36.82, -1.29], [36.82, -1.25], [36.78, -1.25], [36.78, -1.29]]] },
320
+ }),
321
+ kind: 'site-boundary' as const,
322
+ name: 'ZEDD flood site A',
323
+ geometry: { type: 'Polygon', coordinates: [[[36.78, -1.29], [36.82, -1.29], [36.82, -1.25], [36.78, -1.25], [36.78, -1.29]]] },
324
+ };
325
+
326
+ const footprint = rasterFootprintToSpatialObject(manifest); // null when manifest has no bounds
327
+ const claim = createRasterSpatialRelation({
328
+ manifest,
329
+ spatialObject: site,
330
+ relation: 'covers', // raster scene footprint covers the site boundary
331
+ });
332
+ console.log(claim.result.matched); // true (bbox cover)
333
+ console.log(claim.inputs.rasterManifestId); // totem:raster:…
334
+ ```
335
+
336
+ Geometry math, bbox relations, and uncertainty notes are delegated to `@totemsdk/spatial-proof` — nothing here is reimplemented. `covers`/`covered_by`/`intersects`/`overlaps` are bounding-box approximations there and always carry an explicit `uncertainty` note.
337
+
338
+ ## Proofgraph example
339
+
340
+ ```typescript
341
+ import { createProofGraph, addEdge } from '@totemsdk/proofgraph';
342
+ import { rasterManifestToProofGraphNode, rasterManifestToGraphEdges } from '@totemsdk/raster-proof';
343
+
344
+ let graph = createProofGraph();
345
+ graph = addEdge(graph, rasterManifestToGraphEdges(manifest)[0]);
346
+ // custom:<rasterId> node via rasterManifestToProofGraphNode + addNode
347
+ ```
348
+
349
+ Edges represent:
350
+
351
+ - raster `derived_from` source rasters (when derived)
352
+ - raster `references` its spatial object (when present)
353
+ - raster `about` its device / operator / mission (when present)
354
+
355
+ The "raster supports proof" edge is created by `@totemsdk/proofgraph`'s `addProof` when the signed proof is added to the graph.
356
+
357
+ ## Limitations
358
+
359
+ - **Not a raster engine.** No rendering, decoding, projection, or format parsing. Sizes and formats are declared, not verified.
360
+ - **Interpretation is not proven.** A proof binds bytes and metadata; it does not validate a water mask, NDVI value, or defect label. That requires an explicit reviewer/model claim.
361
+ - **Spatial relations are spatial-proof relations.** `covers`/`intersects`/`overlaps`/`covered_by` are bounding-box approximations there, always flagged with `uncertainty`.
362
+ - **Merkle odd-layers promote the last hash** — documented, deterministic, but different from duplication-based trees.
363
+ - **Window proofs carry chunk hashes, not sibling paths.** Full leaf-level re-derivation requires the optional Merkle proofs.
364
+ - **Source rasters are not embedded in proofs** — cross-source derivation verification needs the source manifests supplied separately.
365
+
366
+ ## Security notes
367
+
368
+ - **WOTS one-time keys.** Each WOTS key index can be used exactly once. Never sign two different proofs with the same key index. Reserve indices through [`@totemsdk/wots-lease`](https://www.npmjs.com/package/@totemsdk/wots-lease) before signing.
369
+ - **Content hash binding.** `rasterId` and the evidence hash are derived from stable fields including the content hash — mutating `asset.contentHash`, `layerType`, `sourceType`, or `spatial.bounds` invalidates the ID and the proof.
370
+ - **Provenance is declared, not trusted.** `verifyRasterDerivation` checks structure, not the truthfulness of `derivedFrom` claims. Verify source manifests themselves before trusting a chain.
371
+ - **CRS / bounds are metadata.** Wrong CRS or wrong bounds are detected only by comparing against trusted ground truth.
372
+
373
+ ## Related packages
374
+
375
+ - [`@totemsdk/core`](https://www.npmjs.com/package/@totemsdk/core) — SHA3-256, WOTS signing, script derivation
376
+ - [`@totemsdk/proof`](https://www.npmjs.com/package/@totemsdk/proof) — proof envelopes, signing, verification
377
+ - [`@totemsdk/proofgraph`](https://www.npmjs.com/package/@totemsdk/proofgraph) — content-addressed proof relationship graph
378
+ - [`@totemsdk/location-proof`](https://www.npmjs.com/package/@totemsdk/location-proof) — device-neutral location claims and confidence scoring
379
+ - [`@totemsdk/spatial-proof`](https://www.npmjs.com/package/@totemsdk/spatial-proof) — geospatial relation proofs (geofences, routes, coverage)
380
+ - [`@totemsdk/identity`](https://www.npmjs.com/package/@totemsdk/identity) — device/agent identities
381
+ - [`@totemsdk/manifest`](https://www.npmjs.com/package/@totemsdk/manifest) — signed entity declarations
382
+ - [`@totemsdk/wots-lease`](https://www.npmjs.com/package/@totemsdk/wots-lease) — one-time key safety
383
+ - [`@totemsdk/edge`](https://www.npmjs.com/package/@totemsdk/edge) — unified edge runtime
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Canonical JSON, hashing, and stable ID rules for @totemsdk/raster-proof.
3
+ *
4
+ * canonicalJson and toHex are re-exported from @totemsdk/proof, which is the
5
+ * canonical implementation across the Totem SDK (deterministic canonical JSON
6
+ * with recursively sorted keys, lowercase hex without 0x prefix).
7
+ *
8
+ * ID rules:
9
+ * Raster manifest: "totem:raster:" + sha3_256("totem-raster" + canonicalJson(stableManifest))
10
+ * Raster window: "totem:raster-window:" + sha3_256("totem-raster-window" + canonicalJson(stableWindow))
11
+ *
12
+ * Stable IDs deliberately exclude mutable / non-content fields so equivalent
13
+ * logical content always produces the same identifier:
14
+ * raster manifest: rasterId, metadata
15
+ * raster window: windowProofId, metadata
16
+ */
17
+ import { canonicalJson, toHex } from '@totemsdk/proof';
18
+ import type { RasterManifest, RasterWindowProof } from './types.js';
19
+ export { canonicalJson, toHex };
20
+ /**
21
+ * Compute the stable raster manifest ID: "totem:raster:<sha3-256-hex>".
22
+ * Deterministic over stable fields — the same logical manifest always hashes
23
+ * to the same identifier.
24
+ */
25
+ export declare function computeRasterManifestId(input: Omit<RasterManifest, 'rasterId'>): string;
26
+ /**
27
+ * Hash a complete RasterManifest (excluding rasterId and metadata) to
28
+ * lowercase SHA3-256 hex without a 0x prefix — the value used in
29
+ * EvidenceRef.hash.
30
+ */
31
+ export declare function hashRasterManifest(manifest: RasterManifest): string;
32
+ /**
33
+ * Compute the stable raster window proof ID: "totem:raster-window:<sha3-256-hex>".
34
+ */
35
+ export declare function computeRasterWindowProofId(input: Omit<RasterWindowProof, 'windowProofId'>): string;
36
+ /**
37
+ * Hash a complete RasterWindowProof (excluding windowProofId and metadata)
38
+ * to lowercase SHA3-256 hex without a 0x prefix.
39
+ */
40
+ export declare function hashRasterWindowProof(proof: RasterWindowProof): string;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Canonical JSON, hashing, and stable ID rules for @totemsdk/raster-proof.
4
+ *
5
+ * canonicalJson and toHex are re-exported from @totemsdk/proof, which is the
6
+ * canonical implementation across the Totem SDK (deterministic canonical JSON
7
+ * with recursively sorted keys, lowercase hex without 0x prefix).
8
+ *
9
+ * ID rules:
10
+ * Raster manifest: "totem:raster:" + sha3_256("totem-raster" + canonicalJson(stableManifest))
11
+ * Raster window: "totem:raster-window:" + sha3_256("totem-raster-window" + canonicalJson(stableWindow))
12
+ *
13
+ * Stable IDs deliberately exclude mutable / non-content fields so equivalent
14
+ * logical content always produces the same identifier:
15
+ * raster manifest: rasterId, metadata
16
+ * raster window: windowProofId, metadata
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.toHex = exports.canonicalJson = void 0;
20
+ exports.computeRasterManifestId = computeRasterManifestId;
21
+ exports.hashRasterManifest = hashRasterManifest;
22
+ exports.computeRasterWindowProofId = computeRasterWindowProofId;
23
+ exports.hashRasterWindowProof = hashRasterWindowProof;
24
+ const core_1 = require("@totemsdk/core");
25
+ const proof_1 = require("@totemsdk/proof");
26
+ Object.defineProperty(exports, "canonicalJson", { enumerable: true, get: function () { return proof_1.canonicalJson; } });
27
+ Object.defineProperty(exports, "toHex", { enumerable: true, get: function () { return proof_1.toHex; } });
28
+ const RASTER_PREFIX = 'totem-raster';
29
+ const RASTER_WINDOW_PREFIX = 'totem-raster-window';
30
+ function stableManifestInput(input) {
31
+ const { rasterId: _rasterId, metadata: _metadata, ...stable } = input;
32
+ return stable;
33
+ }
34
+ function stableWindowInput(input) {
35
+ const { windowProofId: _windowProofId, metadata: _metadata, ...stable } = input;
36
+ return stable;
37
+ }
38
+ function hashStableManifest(input) {
39
+ const digest = (0, core_1.sha3_256)(new TextEncoder().encode(RASTER_PREFIX + (0, proof_1.canonicalJson)(stableManifestInput(input))));
40
+ return (0, proof_1.toHex)(digest);
41
+ }
42
+ function hashStableWindow(input) {
43
+ const digest = (0, core_1.sha3_256)(new TextEncoder().encode(RASTER_WINDOW_PREFIX + (0, proof_1.canonicalJson)(stableWindowInput(input))));
44
+ return (0, proof_1.toHex)(digest);
45
+ }
46
+ /**
47
+ * Compute the stable raster manifest ID: "totem:raster:<sha3-256-hex>".
48
+ * Deterministic over stable fields — the same logical manifest always hashes
49
+ * to the same identifier.
50
+ */
51
+ function computeRasterManifestId(input) {
52
+ return 'totem:raster:' + hashStableManifest(input);
53
+ }
54
+ /**
55
+ * Hash a complete RasterManifest (excluding rasterId and metadata) to
56
+ * lowercase SHA3-256 hex without a 0x prefix — the value used in
57
+ * EvidenceRef.hash.
58
+ */
59
+ function hashRasterManifest(manifest) {
60
+ const { rasterId: _rasterId, ...rest } = manifest;
61
+ return hashStableManifest(rest);
62
+ }
63
+ /**
64
+ * Compute the stable raster window proof ID: "totem:raster-window:<sha3-256-hex>".
65
+ */
66
+ function computeRasterWindowProofId(input) {
67
+ return 'totem:raster-window:' + hashStableWindow(input);
68
+ }
69
+ /**
70
+ * Hash a complete RasterWindowProof (excluding windowProofId and metadata)
71
+ * to lowercase SHA3-256 hex without a 0x prefix.
72
+ */
73
+ function hashRasterWindowProof(proof) {
74
+ const { windowProofId: _windowProofId, ...rest } = proof;
75
+ return hashStableWindow(rest);
76
+ }
package/dist/hash.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Byte / string hashing for @totemsdk/raster-proof.
3
+ *
4
+ * SHA3-256 comes from @totemsdk/core. All hashes are lowercase hex without a
5
+ * 0x prefix. No Node crypto, no WASM gating — safe on edge devices.
6
+ */
7
+ /**
8
+ * SHA3-256 hash of raw bytes → lowercase hex (no 0x prefix).
9
+ */
10
+ export declare function hashBytes(bytes: Uint8Array): string;
11
+ /**
12
+ * SHA3-256 hash of a UTF-8 string → lowercase hex (no 0x prefix).
13
+ */
14
+ export declare function hashString(value: string): string;
15
+ /**
16
+ * Hash a chunk's bytes in-place using hashBytes. Kept as a named helper so
17
+ * callers can hash arbitrary sub-byte-ranges without allocating.
18
+ */
19
+ export declare function hashSubarray(bytes: Uint8Array, offset: number, length: number): string;
package/dist/hash.js ADDED
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /**
3
+ * Byte / string hashing for @totemsdk/raster-proof.
4
+ *
5
+ * SHA3-256 comes from @totemsdk/core. All hashes are lowercase hex without a
6
+ * 0x prefix. No Node crypto, no WASM gating — safe on edge devices.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.hashBytes = hashBytes;
10
+ exports.hashString = hashString;
11
+ exports.hashSubarray = hashSubarray;
12
+ const core_1 = require("@totemsdk/core");
13
+ const canonical_js_1 = require("./canonical.js");
14
+ /**
15
+ * SHA3-256 hash of raw bytes → lowercase hex (no 0x prefix).
16
+ */
17
+ function hashBytes(bytes) {
18
+ return (0, canonical_js_1.toHex)((0, core_1.sha3_256)(bytes));
19
+ }
20
+ /**
21
+ * SHA3-256 hash of a UTF-8 string → lowercase hex (no 0x prefix).
22
+ */
23
+ function hashString(value) {
24
+ return (0, canonical_js_1.toHex)((0, core_1.sha3_256)(new TextEncoder().encode(value)));
25
+ }
26
+ /**
27
+ * Hash a chunk's bytes in-place using hashBytes. Kept as a named helper so
28
+ * callers can hash arbitrary sub-byte-ranges without allocating.
29
+ */
30
+ function hashSubarray(bytes, offset, length) {
31
+ return hashBytes(bytes.subarray(offset, offset + length));
32
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @module @totemsdk/raster-proof
3
+ *
4
+ * Edge-capable raster and visual evidence proof primitives for Totem Edge.
5
+ *
6
+ * This package proves bytes, manifests, provenance, windows and declared
7
+ * relationships. It does NOT prove that a visual interpretation is correct
8
+ * unless a reviewer or downstream model proof says so.
9
+ *
10
+ * Pipeline:
11
+ *
12
+ * bytes + asset metadata + spatial context + provenance
13
+ * → chunk hashes / Merkle root
14
+ * → deterministic raster manifest
15
+ * → window proof (optional)
16
+ * → Totem proof envelope
17
+ * → proofgraph linkage
18
+ *
19
+ * This is NOT a raster-processing engine: no GDAL, no GeoTIFF parsing, no
20
+ * satellite provider APIs, no STAC, no cloud masking, no NDVI, no ML
21
+ * segmentation, no orthomosaic generation, no tile server, no storage.
22
+ *
23
+ * No network, no storage, no map rendering, no GIS engine dependency.
24
+ * SHA3-256 everywhere, safe to run on edge devices.
25
+ */
26
+ export type { RasterSourceType, RasterAssetFormat, RasterLayerType, RasterSpatialMetadata, RasterAssetRef, RasterProvenance, RasterManifest, RasterChunk, RasterMerkleProof, RasterWindowProof, RasterValidationResult, RasterMerkleSummary, RasterMerkleOptions, CreateRasterManifestParams, CreateDerivedRasterManifestParams, CreateRasterWindowProofParams, RasterDerivationVerifyResult, CreateRasterSpatialRelationParams, CreateRasterProofParams, RasterProofVerifyResult, } from './types.js';
27
+ export { canonicalJson, toHex } from './canonical.js';
28
+ export { computeRasterManifestId, hashRasterManifest, computeRasterWindowProofId, hashRasterWindowProof, } from './canonical.js';
29
+ export { hashBytes, hashString, hashSubarray, } from './hash.js';
30
+ export { DEFAULT_CHUNK_SIZE_BYTES, chunkBytes, computeMerkleRoot, merkleLeafHash, createMerkleProof, verifyMerkleProof, createRasterMerkleSummary, } from './merkle.js';
31
+ export { createRasterManifest, validateRasterManifest, rasterManifestToEvidenceRef, } from './manifest.js';
32
+ export { createRasterWindowProof, rasterWindowProofToEvidenceRef, } from './window.js';
33
+ export { createDerivedRasterManifest, verifyRasterDerivation, } from './provenance.js';
34
+ export { rasterFootprintToSpatialObject, createRasterSpatialRelation, } from './spatial.js';
35
+ export { rasterEvidenceRefs, createUnsignedRasterProof, signRasterProof, verifyRasterProof, } from './proof.js';
36
+ export { rasterManifestToProofGraphNode, rasterWindowProofToProofGraphNode, rasterManifestToGraphEdges, rasterWindowProofToGraphEdges, addRasterManifestToGraph, } from './proofgraph.js';