@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/dist/proof.js ADDED
@@ -0,0 +1,247 @@
1
+ "use strict";
2
+ /**
3
+ * Proof envelope integration for @totemsdk/raster-proof.
4
+ *
5
+ * Bridges raster manifests, window proofs and Merkle proofs into
6
+ * @totemsdk/proof evidence refs and signed proof envelopes. Signing and
7
+ * verification delegate to @totemsdk/proof. Anchoring is deliberately NOT
8
+ * required for verification.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.rasterEvidenceRefs = rasterEvidenceRefs;
12
+ exports.createUnsignedRasterProof = createUnsignedRasterProof;
13
+ exports.signRasterProof = signRasterProof;
14
+ exports.verifyRasterProof = verifyRasterProof;
15
+ const proof_1 = require("@totemsdk/proof");
16
+ const canonical_js_1 = require("./canonical.js");
17
+ const manifest_js_1 = require("./manifest.js");
18
+ const window_js_1 = require("./window.js");
19
+ const provenance_js_1 = require("./provenance.js");
20
+ const merkle_js_1 = require("./merkle.js");
21
+ /**
22
+ * Build the evidence ref list for a raster proof:
23
+ * - raster manifest hash
24
+ * - content hash
25
+ * - Merkle root when present
26
+ * - window proof hash when present
27
+ * - source raster IDs when derived
28
+ * - spatial object ID when present
29
+ */
30
+ function rasterEvidenceRefs(manifest, windowProof, spatialObjectId) {
31
+ const refs = [
32
+ (0, manifest_js_1.rasterManifestToEvidenceRef)(manifest),
33
+ { id: manifest.asset.contentHash, kind: 'raster-content', hash: manifest.asset.contentHash },
34
+ ];
35
+ if (manifest.asset.merkleRoot) {
36
+ refs.push({ id: manifest.rasterId + ':merkle', kind: 'raster-merkle-root', hash: manifest.asset.merkleRoot });
37
+ }
38
+ if (windowProof) {
39
+ refs.push((0, window_js_1.rasterWindowProofToEvidenceRef)(windowProof));
40
+ }
41
+ if (manifest.provenance?.derivedFrom) {
42
+ for (const src of manifest.provenance.derivedFrom) {
43
+ refs.push({ id: src, kind: 'raster-source', hash: src });
44
+ }
45
+ }
46
+ if (spatialObjectId) {
47
+ refs.push({ id: spatialObjectId, kind: 'spatial-object', hash: spatialObjectId });
48
+ }
49
+ return refs;
50
+ }
51
+ /**
52
+ * Create an unsigned attestation proof for a raster manifest.
53
+ *
54
+ * The proof claims: "this manifest describes this asset, produced by this
55
+ * source, at this time, with this content hash / Merkle root". It does NOT
56
+ * claim the visual interpretation is correct — interpretation is an
57
+ * operator / model / reviewer claim made elsewhere.
58
+ */
59
+ function createUnsignedRasterProof(params) {
60
+ const { manifest, windowProof, merkleProofs, spatialObjectId } = params;
61
+ return (0, proof_1.createProof)({
62
+ kind: 'attestation',
63
+ subject: {
64
+ id: manifest.rasterId,
65
+ kind: 'raster-manifest',
66
+ metadata: {
67
+ sourceType: manifest.sourceType,
68
+ layerType: manifest.layerType,
69
+ },
70
+ },
71
+ issuer: params.issuer ?? manifest.deviceId ?? manifest.operatorId ?? manifest.rasterId,
72
+ issuedAt: params.issuedAt,
73
+ expiresAt: params.expiresAt,
74
+ evidence: rasterEvidenceRefs(manifest, windowProof, spatialObjectId),
75
+ payload: {
76
+ rasterManifest: manifest,
77
+ ...(windowProof ? { windowProof } : {}),
78
+ ...(merkleProofs && merkleProofs.length > 0 ? { merkleProofs } : {}),
79
+ },
80
+ });
81
+ }
82
+ /**
83
+ * Sign an unsigned raster proof with a WOTS key.
84
+ *
85
+ * The caller is responsible for reserving the WOTS key index (see
86
+ * @totemsdk/wots-lease) before calling — one-time key warning applies.
87
+ */
88
+ function signRasterProof(unsigned, seed, keyIndex) {
89
+ return (0, proof_1.signProof)(unsigned, seed, keyIndex);
90
+ }
91
+ /**
92
+ * Verify a window proof payload against the manifest and any supplied Merkle
93
+ * proofs. Returns a failure reason string, or null when valid.
94
+ */
95
+ function checkWindowProof(windowProof, manifest, merkleProofs) {
96
+ const { windowProofId: _wid, ...rest } = windowProof;
97
+ if ((0, canonical_js_1.computeRasterWindowProofId)(rest) !== windowProof.windowProofId) {
98
+ return 'windowProofId does not match recomputed value';
99
+ }
100
+ if (manifest.asset.merkleRoot && windowProof.merkleRoot !== manifest.asset.merkleRoot) {
101
+ return 'window proof merkleRoot does not match manifest asset.merkleRoot';
102
+ }
103
+ if (windowProof.rasterId !== manifest.rasterId) {
104
+ return 'window proof rasterId does not match manifest';
105
+ }
106
+ if (windowProof.chunkIndices.length === 0 || windowProof.chunkIndices.length !== windowProof.chunkHashes.length) {
107
+ return 'window proof chunkIndices must be non-empty and match chunkHashes length';
108
+ }
109
+ for (const proof of merkleProofs ?? []) {
110
+ if (!(0, merkle_js_1.verifyMerkleProof)(proof)) {
111
+ return 'a supplied merkle proof failed verification';
112
+ }
113
+ if (windowProof.merkleRoot && proof.root !== windowProof.merkleRoot) {
114
+ return 'a supplied merkle proof root does not match the window proof root';
115
+ }
116
+ if (!windowProof.chunkIndices.includes(proof.leafIndex)) {
117
+ return 'a supplied merkle proof leafIndex is not referenced by the window proof';
118
+ }
119
+ }
120
+ return null;
121
+ }
122
+ /**
123
+ * Verify a signed raster proof end to end.
124
+ *
125
+ * Checks:
126
+ * 1. the underlying @totemsdk/proof verification (signature, proofId, expiry)
127
+ * 2. payload contains a structurally valid RasterManifest
128
+ * 3. the manifest rasterId matches a recomputation from its fields
129
+ * 4. the manifest evidence hash matches the payload manifest
130
+ * 5. content hash and Merkle root evidence refs are present when declared
131
+ * 6. window proof (when supplied) has a recomputable ID, matches the
132
+ * manifest's Merkle root, and any supplied Merkle proofs verify
133
+ * 7. provenance structure is valid for derived rasters
134
+ *
135
+ * Anchoring is not required. Source raster manifests are not supplied inside
136
+ * the proof, so derivation checks are structural only (full cross-source
137
+ * verification is @totemsdk/raster-proof's verifyRasterDerivation).
138
+ */
139
+ function verifyRasterProof(signed) {
140
+ const base = (0, proof_1.verifyProof)(signed);
141
+ if (!base.valid) {
142
+ return {
143
+ valid: false,
144
+ reason: base.reason,
145
+ signerAddress: base.signerAddress,
146
+ };
147
+ }
148
+ const signerAddress = signed.signature.address;
149
+ const manifest = signed.payload?.['rasterManifest'];
150
+ if (!manifest || typeof manifest !== 'object') {
151
+ return { valid: false, reason: 'payload missing rasterManifest', signerAddress };
152
+ }
153
+ const validation = (0, manifest_js_1.validateRasterManifest)(manifest);
154
+ if (!validation.valid) {
155
+ return {
156
+ valid: false,
157
+ reason: 'payload rasterManifest invalid: ' + validation.errors.join('; '),
158
+ payloadValid: false,
159
+ rasterId: manifest.rasterId,
160
+ signerAddress,
161
+ };
162
+ }
163
+ const { rasterId: _rasterId, ...rest } = manifest;
164
+ if ((0, canonical_js_1.computeRasterManifestId)(rest) !== manifest.rasterId) {
165
+ return {
166
+ valid: false,
167
+ reason: 'rasterId does not match recomputed value',
168
+ rasterIdValid: false,
169
+ rasterId: manifest.rasterId,
170
+ signerAddress,
171
+ };
172
+ }
173
+ const manifestEvidence = signed.evidence?.find((e) => e.id === manifest.rasterId && e.kind === 'raster-manifest');
174
+ if (!manifestEvidence) {
175
+ return {
176
+ valid: false,
177
+ reason: 'evidence missing raster-manifest ref',
178
+ rasterId: manifest.rasterId,
179
+ signerAddress,
180
+ };
181
+ }
182
+ if (manifestEvidence.hash !== (0, canonical_js_1.hashRasterManifest)(manifest)) {
183
+ return {
184
+ valid: false,
185
+ reason: 'evidence hash does not match payload manifest',
186
+ manifestHashValid: false,
187
+ rasterId: manifest.rasterId,
188
+ signerAddress,
189
+ };
190
+ }
191
+ const contentEvidence = signed.evidence?.find((e) => e.kind === 'raster-content');
192
+ if (!contentEvidence || contentEvidence.hash !== manifest.asset.contentHash) {
193
+ return {
194
+ valid: false,
195
+ reason: 'evidence missing or mismatched raster-content hash',
196
+ rasterId: manifest.rasterId,
197
+ signerAddress,
198
+ };
199
+ }
200
+ if (manifest.asset.merkleRoot) {
201
+ const merkleEvidence = signed.evidence?.find((e) => e.kind === 'raster-merkle-root');
202
+ if (!merkleEvidence || merkleEvidence.hash !== manifest.asset.merkleRoot) {
203
+ return {
204
+ valid: false,
205
+ reason: 'evidence missing or mismatched raster-merkle-root',
206
+ rasterId: manifest.rasterId,
207
+ signerAddress,
208
+ };
209
+ }
210
+ }
211
+ const windowProof = signed.payload?.['windowProof'];
212
+ if (windowProof) {
213
+ const merkleProofs = signed.payload?.['merkleProofs'];
214
+ const err = checkWindowProof(windowProof, manifest, merkleProofs);
215
+ if (err) {
216
+ return {
217
+ valid: false,
218
+ reason: err,
219
+ windowProofValid: false,
220
+ rasterId: manifest.rasterId,
221
+ signerAddress,
222
+ };
223
+ }
224
+ }
225
+ if (manifest.sourceType === 'derived') {
226
+ const derivation = (0, provenance_js_1.structuralDerivationCheck)(manifest);
227
+ if (!derivation.valid) {
228
+ return {
229
+ valid: false,
230
+ reason: 'derivation structure invalid: ' + derivation.reasons?.join('; '),
231
+ derivationValid: false,
232
+ rasterId: manifest.rasterId,
233
+ signerAddress,
234
+ };
235
+ }
236
+ }
237
+ return {
238
+ valid: true,
239
+ signerAddress,
240
+ rasterId: manifest.rasterId,
241
+ payloadValid: true,
242
+ rasterIdValid: true,
243
+ manifestHashValid: true,
244
+ ...(windowProof ? { windowProofValid: true } : {}),
245
+ ...(manifest.sourceType === 'derived' ? { derivationValid: true } : {}),
246
+ };
247
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Proofgraph integration helpers for @totemsdk/raster-proof.
3
+ *
4
+ * Produces nodes and edges for @totemsdk/proofgraph without storage
5
+ * assumptions. Helpers never mutate a graph directly — callers combine the
6
+ * returned nodes/edges with addNode/addEdge.
7
+ *
8
+ * Note: @totemsdk/proofgraph has no native 'raster' node type, so raster
9
+ * manifests and window proofs map to the generic 'custom' node type (the
10
+ * same approach @totemsdk/location-proof and @totemsdk/spatial-proof use).
11
+ * If a dedicated 'raster' node type is ever wanted, propose it in
12
+ * @totemsdk/proofgraph (do not silently fork the vocabulary).
13
+ */
14
+ import type { ProofGraph, ProofGraphNode, ProofGraphEdge } from '@totemsdk/proofgraph';
15
+ import type { RasterManifest, RasterWindowProof } from './types.js';
16
+ /**
17
+ * Build a ProofGraphNode for a raster manifest ('custom' type).
18
+ * Node ID is deterministic: "custom:<rasterId>".
19
+ */
20
+ export declare function rasterManifestToProofGraphNode(manifest: RasterManifest): ProofGraphNode;
21
+ /**
22
+ * Build a ProofGraphNode for a raster window proof ('custom' type).
23
+ * Node ID is deterministic: "custom:<windowProofId>".
24
+ */
25
+ export declare function rasterWindowProofToProofGraphNode(windowProof: RasterWindowProof): ProofGraphNode;
26
+ /**
27
+ * Build ProofGraphEdges for a raster manifest:
28
+ * derived_from raster → each source raster (when provenance.derivedFrom)
29
+ * references raster → spatial object (when spatial.spatialObjectId)
30
+ * about raster → device (when deviceId)
31
+ * about raster → subject(operator) (when operatorId)
32
+ * about raster → subject(mission) (when missionId)
33
+ * references window proof → raster (see rasterWindowProofToGraphEdges)
34
+ *
35
+ * The "raster supports proof" edge is created by @totemsdk/proofgraph's
36
+ * addProof when the signed proof is added to the graph — this helper has no
37
+ * proof to link at construction time.
38
+ *
39
+ * Edge IDs are deterministic (content-derived in @totemsdk/proofgraph).
40
+ */
41
+ export declare function rasterManifestToGraphEdges(manifest: RasterManifest): ProofGraphEdge[];
42
+ /**
43
+ * Build ProofGraphEdges for a raster window proof:
44
+ * derived_from window proof → raster
45
+ */
46
+ export declare function rasterWindowProofToGraphEdges(windowProof: RasterWindowProof): ProofGraphEdge[];
47
+ /**
48
+ * Add a raster manifest as a 'custom' node to a proof graph (immutable —
49
+ * returns a new graph).
50
+ */
51
+ export declare function addRasterManifestToGraph(graph: ProofGraph, manifest: RasterManifest): ProofGraph;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * Proofgraph integration helpers for @totemsdk/raster-proof.
4
+ *
5
+ * Produces nodes and edges for @totemsdk/proofgraph without storage
6
+ * assumptions. Helpers never mutate a graph directly — callers combine the
7
+ * returned nodes/edges with addNode/addEdge.
8
+ *
9
+ * Note: @totemsdk/proofgraph has no native 'raster' node type, so raster
10
+ * manifests and window proofs map to the generic 'custom' node type (the
11
+ * same approach @totemsdk/location-proof and @totemsdk/spatial-proof use).
12
+ * If a dedicated 'raster' node type is ever wanted, propose it in
13
+ * @totemsdk/proofgraph (do not silently fork the vocabulary).
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.rasterManifestToProofGraphNode = rasterManifestToProofGraphNode;
17
+ exports.rasterWindowProofToProofGraphNode = rasterWindowProofToProofGraphNode;
18
+ exports.rasterManifestToGraphEdges = rasterManifestToGraphEdges;
19
+ exports.rasterWindowProofToGraphEdges = rasterWindowProofToGraphEdges;
20
+ exports.addRasterManifestToGraph = addRasterManifestToGraph;
21
+ const proofgraph_1 = require("@totemsdk/proofgraph");
22
+ /**
23
+ * Build a ProofGraphNode for a raster manifest ('custom' type).
24
+ * Node ID is deterministic: "custom:<rasterId>".
25
+ */
26
+ function rasterManifestToProofGraphNode(manifest) {
27
+ return {
28
+ id: (0, proofgraph_1.computeNodeId)('custom', manifest.rasterId),
29
+ type: 'custom',
30
+ refId: manifest.rasterId,
31
+ data: {
32
+ kind: 'raster-manifest',
33
+ sourceType: manifest.sourceType,
34
+ layerType: manifest.layerType,
35
+ contentHash: manifest.asset.contentHash,
36
+ ...(manifest.asset.merkleRoot ? { merkleRoot: manifest.asset.merkleRoot } : {}),
37
+ ...(manifest.spatial?.spatialObjectId ? { spatialObjectId: manifest.spatial.spatialObjectId } : {}),
38
+ ...(manifest.deviceId ? { deviceId: manifest.deviceId } : {}),
39
+ },
40
+ createdAt: manifest.createdAt,
41
+ };
42
+ }
43
+ /**
44
+ * Build a ProofGraphNode for a raster window proof ('custom' type).
45
+ * Node ID is deterministic: "custom:<windowProofId>".
46
+ */
47
+ function rasterWindowProofToProofGraphNode(windowProof) {
48
+ return {
49
+ id: (0, proofgraph_1.computeNodeId)('custom', windowProof.windowProofId),
50
+ type: 'custom',
51
+ refId: windowProof.windowProofId,
52
+ data: {
53
+ kind: 'raster-window-proof',
54
+ rasterId: windowProof.rasterId,
55
+ merkleRoot: windowProof.merkleRoot,
56
+ chunkIndices: windowProof.chunkIndices,
57
+ hashes: windowProof.chunkHashes,
58
+ },
59
+ createdAt: windowProof.createdAt,
60
+ };
61
+ }
62
+ /**
63
+ * Build ProofGraphEdges for a raster manifest:
64
+ * derived_from raster → each source raster (when provenance.derivedFrom)
65
+ * references raster → spatial object (when spatial.spatialObjectId)
66
+ * about raster → device (when deviceId)
67
+ * about raster → subject(operator) (when operatorId)
68
+ * about raster → subject(mission) (when missionId)
69
+ * references window proof → raster (see rasterWindowProofToGraphEdges)
70
+ *
71
+ * The "raster supports proof" edge is created by @totemsdk/proofgraph's
72
+ * addProof when the signed proof is added to the graph — this helper has no
73
+ * proof to link at construction time.
74
+ *
75
+ * Edge IDs are deterministic (content-derived in @totemsdk/proofgraph).
76
+ */
77
+ function rasterManifestToGraphEdges(manifest) {
78
+ const edges = [];
79
+ for (const src of manifest.provenance?.derivedFrom ?? []) {
80
+ edges.push((0, proofgraph_1.buildEdge)('derived_from', manifest.rasterId, src, manifest.rasterId, {
81
+ kind: 'raster-source',
82
+ }));
83
+ }
84
+ if (manifest.spatial?.spatialObjectId) {
85
+ edges.push((0, proofgraph_1.buildEdge)('references', manifest.rasterId, manifest.spatial.spatialObjectId, manifest.rasterId, {
86
+ kind: 'spatial-object',
87
+ }));
88
+ }
89
+ if (manifest.deviceId) {
90
+ edges.push((0, proofgraph_1.buildEdge)('about', manifest.rasterId, manifest.deviceId, manifest.rasterId, { kind: 'device' }));
91
+ }
92
+ if (manifest.operatorId) {
93
+ edges.push((0, proofgraph_1.buildEdge)('about', manifest.rasterId, manifest.operatorId, manifest.rasterId, { kind: 'operator' }));
94
+ }
95
+ if (manifest.missionId) {
96
+ edges.push((0, proofgraph_1.buildEdge)('about', manifest.rasterId, manifest.missionId, manifest.rasterId, { kind: 'mission' }));
97
+ }
98
+ return edges;
99
+ }
100
+ /**
101
+ * Build ProofGraphEdges for a raster window proof:
102
+ * derived_from window proof → raster
103
+ */
104
+ function rasterWindowProofToGraphEdges(windowProof) {
105
+ return [
106
+ (0, proofgraph_1.buildEdge)('derived_from', windowProof.windowProofId, windowProof.rasterId, windowProof.windowProofId, {
107
+ kind: 'raster-window-proof',
108
+ }),
109
+ ];
110
+ }
111
+ /**
112
+ * Add a raster manifest as a 'custom' node to a proof graph (immutable —
113
+ * returns a new graph).
114
+ */
115
+ function addRasterManifestToGraph(graph, manifest) {
116
+ return (0, proofgraph_1.addNode)(graph, 'custom', manifest.rasterId, {
117
+ kind: 'raster-manifest',
118
+ ...manifest,
119
+ });
120
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Derived raster provenance for @totemsdk/raster-proof.
3
+ *
4
+ * createDerivedRasterManifest records a raster produced from other rasters
5
+ * (satellite scene → water mask, image set → orthomosaic, before/after →
6
+ * change mask, …). verifyRasterDerivation checks the DECLARED provenance
7
+ * structure — that every derivedFrom ID is supplied, parameters are present
8
+ * when a pipeline is named, and the manifest is honestly marked as derived.
9
+ *
10
+ * It does NOT verify that image processing was performed correctly. That is
11
+ * outside this package's scope.
12
+ */
13
+ import type { CreateDerivedRasterManifestParams, RasterDerivationVerifyResult, RasterManifest } from './types.js';
14
+ /**
15
+ * Create a derived raster manifest from source rasters. sourceType is forced
16
+ * to 'derived'; provenance.derivedFrom lists the source raster IDs.
17
+ */
18
+ export declare function createDerivedRasterManifest(params: CreateDerivedRasterManifestParams): RasterManifest;
19
+ /**
20
+ * Structural derivation check (no source manifests required). Used both by
21
+ * verifyRasterDerivation (with sources) and by proof verification (where the
22
+ * signer's source rasters are not inside the proof).
23
+ */
24
+ export declare function structuralDerivationCheck(manifest: RasterManifest): Omit<RasterDerivationVerifyResult, 'sourceRasterIds' | 'missingSources'>;
25
+ /**
26
+ * Verify the declared provenance structure of a derived raster manifest
27
+ * against the supplied source manifests.
28
+ */
29
+ export declare function verifyRasterDerivation(manifest: RasterManifest, sourceManifests: RasterManifest[]): RasterDerivationVerifyResult;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * Derived raster provenance for @totemsdk/raster-proof.
4
+ *
5
+ * createDerivedRasterManifest records a raster produced from other rasters
6
+ * (satellite scene → water mask, image set → orthomosaic, before/after →
7
+ * change mask, …). verifyRasterDerivation checks the DECLARED provenance
8
+ * structure — that every derivedFrom ID is supplied, parameters are present
9
+ * when a pipeline is named, and the manifest is honestly marked as derived.
10
+ *
11
+ * It does NOT verify that image processing was performed correctly. That is
12
+ * outside this package's scope.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.createDerivedRasterManifest = createDerivedRasterManifest;
16
+ exports.structuralDerivationCheck = structuralDerivationCheck;
17
+ exports.verifyRasterDerivation = verifyRasterDerivation;
18
+ const manifest_js_1 = require("./manifest.js");
19
+ /**
20
+ * Create a derived raster manifest from source rasters. sourceType is forced
21
+ * to 'derived'; provenance.derivedFrom lists the source raster IDs.
22
+ */
23
+ function createDerivedRasterManifest(params) {
24
+ const { sourceManifests, layerType, asset, pipelineId, pipelineVersion, parametersHash, modelId, uncertainty, operatorId, ...rest } = params;
25
+ if (sourceManifests.length === 0) {
26
+ throw new Error('a derived raster requires at least one source manifest');
27
+ }
28
+ if (pipelineId !== undefined && parametersHash === undefined) {
29
+ throw new Error('parametersHash is required when pipelineId is set');
30
+ }
31
+ return (0, manifest_js_1.createRasterManifest)({
32
+ sourceType: 'derived',
33
+ layerType,
34
+ asset,
35
+ provenance: {
36
+ derivedFrom: sourceManifests.map((m) => m.rasterId),
37
+ ...(pipelineId !== undefined ? { pipelineId } : {}),
38
+ ...(pipelineVersion !== undefined ? { pipelineVersion } : {}),
39
+ ...(parametersHash !== undefined ? { parametersHash } : {}),
40
+ ...(modelId !== undefined ? { modelId } : {}),
41
+ ...(uncertainty !== undefined && uncertainty.length > 0 ? { uncertainty } : {}),
42
+ ...(operatorId !== undefined ? { operatorId } : {}),
43
+ },
44
+ ...rest,
45
+ });
46
+ }
47
+ /**
48
+ * Structural derivation check (no source manifests required). Used both by
49
+ * verifyRasterDerivation (with sources) and by proof verification (where the
50
+ * signer's source rasters are not inside the proof).
51
+ */
52
+ function structuralDerivationCheck(manifest) {
53
+ const reasons = [];
54
+ if (manifest.sourceType !== 'derived') {
55
+ reasons.push('manifest.sourceType must be "derived"');
56
+ }
57
+ if (!manifest.asset || typeof manifest.asset.contentHash !== 'string' || manifest.asset.contentHash.length === 0) {
58
+ reasons.push('derived raster must declare asset.contentHash');
59
+ }
60
+ const derivedFrom = manifest.provenance?.derivedFrom ?? [];
61
+ if (derivedFrom.length === 0) {
62
+ reasons.push('derived raster must declare provenance.derivedFrom');
63
+ }
64
+ if (manifest.provenance?.pipelineId !== undefined && manifest.provenance.parametersHash === undefined) {
65
+ reasons.push('parametersHash is required when pipelineId is present');
66
+ }
67
+ if (manifest.provenance?.uncertainty !== undefined) {
68
+ const bad = manifest.provenance.uncertainty.some((u) => typeof u !== 'string' || u.length === 0);
69
+ if (bad) {
70
+ reasons.push('provenance.uncertainty must be an array of non-empty strings');
71
+ }
72
+ }
73
+ return { valid: reasons.length === 0, ...(reasons.length > 0 ? { reasons } : {}) };
74
+ }
75
+ /**
76
+ * Verify the declared provenance structure of a derived raster manifest
77
+ * against the supplied source manifests.
78
+ */
79
+ function verifyRasterDerivation(manifest, sourceManifests) {
80
+ const structural = structuralDerivationCheck(manifest);
81
+ const reasons = structural.reasons ?? [];
82
+ const derivedFrom = manifest.provenance?.derivedFrom ?? [];
83
+ const supplied = new Set(sourceManifests.map((m) => m.rasterId));
84
+ const missing = derivedFrom.filter((id) => !supplied.has(id));
85
+ if (missing.length > 0) {
86
+ reasons.push(`derivedFrom references missing source rasters: ${missing.join(', ')}`);
87
+ }
88
+ return {
89
+ valid: reasons.length === 0,
90
+ ...(reasons.length > 0 ? { reasons } : {}),
91
+ sourceRasterIds: derivedFrom,
92
+ ...(missing.length > 0 ? { missingSources: missing } : {}),
93
+ ...(manifest.provenance?.uncertainty !== undefined ? { uncertainty: manifest.provenance.uncertainty } : {}),
94
+ };
95
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @totemsdk/spatial-proof integration for @totemsdk/raster-proof.
3
+ *
4
+ * Bridges a raster manifest's bounds into a @totemsdk/spatial-proof
5
+ * SpatialObject and evaluates spatial relations (covers, intersects,
6
+ * overlaps, covered_by, …) against site boundaries, zones, routes, scene
7
+ * footprints and inspection areas. All geometry math is delegated to
8
+ * @totemsdk/spatial-proof — nothing here is reimplemented.
9
+ */
10
+ import type { SpatialObject, SpatialRelationClaim, SpatialRelationType } from '@totemsdk/spatial-proof';
11
+ import type { CreateRasterSpatialRelationParams, RasterManifest } from './types.js';
12
+ /**
13
+ * Convert a raster manifest into a spatial object footprint, or null when the
14
+ * manifest has no bounds (nothing to georeference).
15
+ */
16
+ export declare function rasterFootprintToSpatialObject(manifest: RasterManifest): SpatialObject | null;
17
+ /**
18
+ * Evaluate a spatial relation between a raster footprint and a spatial
19
+ * object, producing a deterministic SpatialRelationClaim via
20
+ * @totemsdk/spatial-proof. Requires the manifest to have bounds.
21
+ */
22
+ export declare function createRasterSpatialRelation(params: CreateRasterSpatialRelationParams): SpatialRelationClaim;
23
+ export type { SpatialRelationType };
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * @totemsdk/spatial-proof integration for @totemsdk/raster-proof.
4
+ *
5
+ * Bridges a raster manifest's bounds into a @totemsdk/spatial-proof
6
+ * SpatialObject and evaluates spatial relations (covers, intersects,
7
+ * overlaps, covered_by, …) against site boundaries, zones, routes, scene
8
+ * footprints and inspection areas. All geometry math is delegated to
9
+ * @totemsdk/spatial-proof — nothing here is reimplemented.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.rasterFootprintToSpatialObject = rasterFootprintToSpatialObject;
13
+ exports.createRasterSpatialRelation = createRasterSpatialRelation;
14
+ const spatial_proof_1 = require("@totemsdk/spatial-proof");
15
+ /**
16
+ * Build a bbox Polygon (GeoJSON [lon, lat], closed ring) from manifest bounds.
17
+ */
18
+ function footprintPolygon(bounds) {
19
+ const [minLon, minLat, maxLon, maxLat] = bounds;
20
+ return {
21
+ type: 'Polygon',
22
+ coordinates: [[
23
+ [minLon, minLat],
24
+ [maxLon, minLat],
25
+ [maxLon, maxLat],
26
+ [minLon, maxLat],
27
+ [minLon, minLat],
28
+ ]],
29
+ };
30
+ }
31
+ /**
32
+ * Convert a raster manifest into a spatial object footprint, or null when the
33
+ * manifest has no bounds (nothing to georeference).
34
+ */
35
+ function rasterFootprintToSpatialObject(manifest) {
36
+ const bounds = manifest.spatial?.bounds;
37
+ if (!bounds || bounds.length !== 4) {
38
+ return null;
39
+ }
40
+ const geometry = footprintPolygon(bounds);
41
+ const body = {
42
+ kind: 'scene-footprint',
43
+ geometry,
44
+ ...(manifest.spatial?.crs !== undefined ? { crs: manifest.spatial.crs } : {}),
45
+ ...(manifest.spatial?.spatialObjectId !== undefined ? { spatialId: manifest.spatial.spatialObjectId } : {}),
46
+ ...(manifest.rasterId !== undefined ? { name: `raster ${manifest.rasterId}` } : {}),
47
+ };
48
+ const spatialObject = {
49
+ ...body,
50
+ spatialId: body.spatialId ?? (0, spatial_proof_1.computeSpatialObjectId)(body),
51
+ };
52
+ return spatialObject;
53
+ }
54
+ /**
55
+ * Evaluate a spatial relation between a raster footprint and a spatial
56
+ * object, producing a deterministic SpatialRelationClaim via
57
+ * @totemsdk/spatial-proof. Requires the manifest to have bounds.
58
+ */
59
+ function createRasterSpatialRelation(params) {
60
+ const { manifest, spatialObject, relation, computedAt, maxDistanceM, subjectProofId, metadata } = params;
61
+ const bounds = manifest.spatial?.bounds;
62
+ if (!bounds || bounds.length !== 4) {
63
+ throw new Error('createRasterSpatialRelation requires manifest.spatial.bounds');
64
+ }
65
+ return (0, spatial_proof_1.evaluateSpatialRelation)({
66
+ subjectId: manifest.rasterId,
67
+ subjectKind: 'raster-manifest',
68
+ spatialObject,
69
+ relation,
70
+ subjectGeometry: footprintPolygon(bounds),
71
+ rasterManifestId: manifest.rasterId,
72
+ ...(computedAt !== undefined ? { computedAt } : {}),
73
+ ...(maxDistanceM !== undefined ? { maxDistanceM } : {}),
74
+ ...(subjectProofId !== undefined ? { subjectProofId } : {}),
75
+ ...(metadata !== undefined ? { metadata } : {}),
76
+ });
77
+ }