@totemsdk/proofgraph 1.0.1 → 1.1.1
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 +202 -21
- package/NOTICE +60 -0
- package/README.md +31 -10
- package/dist/canonical.js +11 -19
- package/dist/cjs/canonical.d.ts +22 -0
- package/dist/cjs/canonical.js +51 -0
- package/dist/cjs/durable-store.d.ts +50 -0
- package/dist/cjs/durable-store.js +178 -0
- package/dist/cjs/evidence.d.ts +89 -0
- package/dist/cjs/evidence.js +130 -0
- package/dist/cjs/graph.d.ts +103 -0
- package/dist/cjs/graph.js +298 -0
- package/dist/cjs/index.d.ts +26 -0
- package/dist/cjs/index.js +84 -0
- package/dist/cjs/io.d.ts +26 -0
- package/dist/cjs/io.js +173 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/query.d.ts +85 -0
- package/dist/cjs/query.js +189 -0
- package/dist/cjs/replicated-evidence.d.ts +42 -0
- package/dist/cjs/replicated-evidence.js +98 -0
- package/dist/cjs/types.d.ts +62 -0
- package/dist/cjs/types.js +7 -0
- package/dist/cjs/verify.d.ts +23 -0
- package/dist/cjs/verify.js +77 -0
- package/dist/durable-store.js +9 -12
- package/dist/evidence.js +14 -19
- package/dist/graph.d.ts +11 -0
- package/dist/graph.js +47 -34
- package/dist/index.d.ts +3 -2
- package/dist/index.js +8 -52
- package/dist/io.js +4 -8
- package/dist/query.d.ts +4 -0
- package/dist/query.js +30 -38
- package/dist/replicated-evidence.d.ts +42 -0
- package/dist/replicated-evidence.js +95 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -2
- package/dist/verify.js +3 -40
- package/package.json +25 -15
- package/rust/pkg/package.json +2 -2
- package/rust/pkg/proofgraph_wasm_bg.wasm +0 -0
- package/rust/pkg-node/package.json +2 -2
- package/rust/pkg-node/proofgraph_wasm_bg.wasm +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Proof graph mutation functions — all pure, all returning NEW graphs.
|
|
4
|
+
*
|
|
5
|
+
* Immutable pattern: every mutation returns a brand-new ProofGraph with a
|
|
6
|
+
* recomputed graphId. Nodes and edges are deduplicated by ID so adding the
|
|
7
|
+
* same proof twice is idempotent.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createProofGraph = createProofGraph;
|
|
11
|
+
exports.setGraphMetadata = setGraphMetadata;
|
|
12
|
+
exports.buildEdge = buildEdge;
|
|
13
|
+
exports.addNode = addNode;
|
|
14
|
+
exports.addEdge = addEdge;
|
|
15
|
+
exports.addIdentityDocument = addIdentityDocument;
|
|
16
|
+
exports.addProof = addProof;
|
|
17
|
+
exports.addIdentityClaim = addIdentityClaim;
|
|
18
|
+
exports.addManifest = addManifest;
|
|
19
|
+
exports.addManifestRevision = addManifestRevision;
|
|
20
|
+
exports.addReceiptLike = addReceiptLike;
|
|
21
|
+
exports.addAnchor = addAnchor;
|
|
22
|
+
const manifest_1 = require("@totemsdk/manifest");
|
|
23
|
+
const canonical_js_1 = require("./canonical.js");
|
|
24
|
+
const evidence_js_1 = require("./evidence.js");
|
|
25
|
+
function makeNode(type, refId, data) {
|
|
26
|
+
return {
|
|
27
|
+
id: (0, canonical_js_1.computeNodeId)(type, refId),
|
|
28
|
+
type,
|
|
29
|
+
refId,
|
|
30
|
+
...(data !== undefined ? { data } : {}),
|
|
31
|
+
createdAt: Date.now(),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function makeEdge(type, from, to, proofId, data) {
|
|
35
|
+
return {
|
|
36
|
+
id: (0, canonical_js_1.computeEdgeId)(type, from, to, proofId, data),
|
|
37
|
+
type,
|
|
38
|
+
from,
|
|
39
|
+
to,
|
|
40
|
+
...(proofId !== undefined ? { proofId } : {}),
|
|
41
|
+
...(data !== undefined ? { data } : {}),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function mergeNodes(existing, incoming) {
|
|
45
|
+
const byId = new Map(existing.map((n) => [n.id, n]));
|
|
46
|
+
for (const node of incoming) {
|
|
47
|
+
if (!byId.has(node.id)) {
|
|
48
|
+
byId.set(node.id, node);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return Array.from(byId.values());
|
|
52
|
+
}
|
|
53
|
+
function mergeEdges(existing, incoming) {
|
|
54
|
+
const byId = new Map(existing.map((e) => [e.id, e]));
|
|
55
|
+
for (const edge of incoming) {
|
|
56
|
+
if (!byId.has(edge.id)) {
|
|
57
|
+
byId.set(edge.id, edge);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return Array.from(byId.values());
|
|
61
|
+
}
|
|
62
|
+
function rebuild(graph, newNodes, newEdges) {
|
|
63
|
+
const nodes = mergeNodes(graph.nodes, newNodes);
|
|
64
|
+
const edges = mergeEdges(graph.edges, newEdges);
|
|
65
|
+
return {
|
|
66
|
+
...graph,
|
|
67
|
+
nodes,
|
|
68
|
+
edges,
|
|
69
|
+
graphId: (0, canonical_js_1.computeProofGraphId)(nodes, edges),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create an empty ProofGraph.
|
|
74
|
+
*/
|
|
75
|
+
function createProofGraph(metadata) {
|
|
76
|
+
const nodes = [];
|
|
77
|
+
const edges = [];
|
|
78
|
+
return {
|
|
79
|
+
graphId: (0, canonical_js_1.computeProofGraphId)(nodes, edges),
|
|
80
|
+
nodes,
|
|
81
|
+
edges,
|
|
82
|
+
createdAt: Date.now(),
|
|
83
|
+
...(metadata !== undefined ? { metadata } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Attach or replace mutable metadata. Does NOT affect graphId.
|
|
88
|
+
*/
|
|
89
|
+
function setGraphMetadata(graph, metadata) {
|
|
90
|
+
return { ...graph, metadata };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Build a ProofGraphEdge with a deterministic ID from its fields.
|
|
94
|
+
* Convenience helper so callers don't need to import computeEdgeId.
|
|
95
|
+
*/
|
|
96
|
+
function buildEdge(type, from, to, proofId, data) {
|
|
97
|
+
return makeEdge(type, from, to, proofId, data);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Add a node directly (type + refId pair). Idempotent — skipped if the node already exists.
|
|
101
|
+
*/
|
|
102
|
+
function addNode(graph, type, refId, data) {
|
|
103
|
+
return rebuild(graph, [makeNode(type, refId, data)], []);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Append a ProofGraphEdge and recompute graphId. Idempotent by edge ID.
|
|
107
|
+
* Spec API: addEdge(graph, edge). Use buildEdge() to construct the edge object.
|
|
108
|
+
*/
|
|
109
|
+
function addEdge(graph, edge) {
|
|
110
|
+
const edges = mergeEdges(graph.edges, [edge]);
|
|
111
|
+
return {
|
|
112
|
+
...graph,
|
|
113
|
+
edges,
|
|
114
|
+
graphId: (0, canonical_js_1.computeProofGraphId)(graph.nodes, edges),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Index a TotemIdentityDocument into the graph.
|
|
119
|
+
* Creates an 'identity' node with refId = doc.id.
|
|
120
|
+
*/
|
|
121
|
+
function addIdentityDocument(graph, doc) {
|
|
122
|
+
return rebuild(graph, [makeNode('identity', doc.id, { ...doc })], []);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Index a SignedProof into the graph.
|
|
126
|
+
*
|
|
127
|
+
* Nodes created:
|
|
128
|
+
* proof — proofId (stores the full SignedProof in .data)
|
|
129
|
+
* identity — signature.address (issuer key address)
|
|
130
|
+
* subject — proof.subject.id
|
|
131
|
+
* evidence — ev.id (one per evidence ref)
|
|
132
|
+
* anchor — anchor.hash (if present)
|
|
133
|
+
*
|
|
134
|
+
* Edges created (all referencing the proofId):
|
|
135
|
+
* proves proof → subject
|
|
136
|
+
* issued_by proof → identity (signer)
|
|
137
|
+
* about proof → subject
|
|
138
|
+
* references proof → evidence (one per evidence ref, in array order)
|
|
139
|
+
* anchored_to proof → anchor (if present)
|
|
140
|
+
*/
|
|
141
|
+
function addProof(graph, signedProof) {
|
|
142
|
+
const proofNode = makeNode('proof', signedProof.proofId, {
|
|
143
|
+
...signedProof,
|
|
144
|
+
});
|
|
145
|
+
const identityNode = makeNode('identity', signedProof.signature.address);
|
|
146
|
+
const subjectNode = makeNode('subject', signedProof.subject.id);
|
|
147
|
+
const newNodes = [proofNode, identityNode, subjectNode];
|
|
148
|
+
const newEdges = [
|
|
149
|
+
makeEdge('proves', signedProof.proofId, signedProof.subject.id, signedProof.proofId),
|
|
150
|
+
makeEdge('issued_by', signedProof.proofId, signedProof.signature.address, signedProof.proofId),
|
|
151
|
+
makeEdge('about', signedProof.proofId, signedProof.subject.id, signedProof.proofId),
|
|
152
|
+
];
|
|
153
|
+
if (signedProof.evidence) {
|
|
154
|
+
for (const ev of signedProof.evidence) {
|
|
155
|
+
// RFC-007 Amendment A (A3): carry the claim commitment on the evidence
|
|
156
|
+
// node so the evidence store can enforce claim→contentHash→artifact.
|
|
157
|
+
newNodes.push(makeNode('evidence', ev.id, ev.hash ? { contentHash: (0, evidence_js_1.normalizeEvidenceHash)(ev.hash) } : undefined));
|
|
158
|
+
newEdges.push(makeEdge('references', signedProof.proofId, ev.id, signedProof.proofId));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (signedProof.anchor) {
|
|
162
|
+
newNodes.push(makeNode('anchor', signedProof.anchor.hash));
|
|
163
|
+
newEdges.push(makeEdge('anchored_to', signedProof.proofId, signedProof.anchor.hash, signedProof.proofId));
|
|
164
|
+
}
|
|
165
|
+
return rebuild(graph, newNodes, newEdges);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Index a SignedIdentityClaim into the graph.
|
|
169
|
+
*
|
|
170
|
+
* Nodes created:
|
|
171
|
+
* identity-claim — claim.id (stores the full signed claim in .data)
|
|
172
|
+
* address — issuer address
|
|
173
|
+
* address/identity — target address (for delegates_to / rotates_to / revokes)
|
|
174
|
+
*
|
|
175
|
+
* Edges created based on claim.type:
|
|
176
|
+
* all types → issued_by (claim-node → issuer address)
|
|
177
|
+
* delegates_to → delegates_to edge (claim-node → delegated address)
|
|
178
|
+
* revokes → revokes edge (claim-node → subject identity)
|
|
179
|
+
* rotates_to → controls edge (claim-node → new address)
|
|
180
|
+
*/
|
|
181
|
+
function addIdentityClaim(graph, signedClaim) {
|
|
182
|
+
const { claim } = signedClaim;
|
|
183
|
+
const claimNode = makeNode('identity-claim', claim.id, {
|
|
184
|
+
...signedClaim,
|
|
185
|
+
});
|
|
186
|
+
const issuerNode = makeNode('address', claim.issuer);
|
|
187
|
+
const newNodes = [claimNode, issuerNode];
|
|
188
|
+
const newEdges = [
|
|
189
|
+
makeEdge('issued_by', claim.id, claim.issuer),
|
|
190
|
+
];
|
|
191
|
+
if (claim.type === 'delegates_to') {
|
|
192
|
+
newNodes.push(makeNode('address', claim.object));
|
|
193
|
+
newEdges.push(makeEdge('delegates_to', claim.id, claim.object));
|
|
194
|
+
}
|
|
195
|
+
else if (claim.type === 'revokes') {
|
|
196
|
+
newNodes.push(makeNode('identity', claim.subject));
|
|
197
|
+
newEdges.push(makeEdge('revokes', claim.id, claim.subject));
|
|
198
|
+
}
|
|
199
|
+
else if (claim.type === 'rotates_to') {
|
|
200
|
+
newNodes.push(makeNode('address', claim.object));
|
|
201
|
+
newEdges.push(makeEdge('controls', claim.id, claim.object));
|
|
202
|
+
}
|
|
203
|
+
return rebuild(graph, newNodes, newEdges);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolve the author address from a manifest based on its type.
|
|
207
|
+
* AppManifest / DAppManifest → authorAddress
|
|
208
|
+
* CapabilityManifest → agentAddress
|
|
209
|
+
* EdgeServiceManifest → operatorAddress
|
|
210
|
+
* Falls back to signedManifest.authorAddress if the manifest type is unknown.
|
|
211
|
+
*/
|
|
212
|
+
function resolveManifestAddress(signedManifest) {
|
|
213
|
+
const m = signedManifest.manifest;
|
|
214
|
+
if (m['type'] === 'capability' && typeof m['agentAddress'] === 'string') {
|
|
215
|
+
return m['agentAddress'];
|
|
216
|
+
}
|
|
217
|
+
if (m['type'] === 'edge-service' && typeof m['operatorAddress'] === 'string') {
|
|
218
|
+
return m['operatorAddress'];
|
|
219
|
+
}
|
|
220
|
+
if (typeof m['authorAddress'] === 'string') {
|
|
221
|
+
return m['authorAddress'];
|
|
222
|
+
}
|
|
223
|
+
return signedManifest.authorAddress;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Index a SignedManifest into the graph.
|
|
227
|
+
*
|
|
228
|
+
* Nodes created:
|
|
229
|
+
* manifest — computed manifest ID (stores manifest content in .data)
|
|
230
|
+
* address — resolved author/agent/operator address
|
|
231
|
+
*
|
|
232
|
+
* Edge created:
|
|
233
|
+
* manifests_as manifest → address
|
|
234
|
+
*/
|
|
235
|
+
function addManifest(graph, signedManifest) {
|
|
236
|
+
const manifestId = (0, manifest_1.computeManifestId)(signedManifest.manifest);
|
|
237
|
+
const address = resolveManifestAddress(signedManifest);
|
|
238
|
+
const manifestNode = makeNode('manifest', manifestId, {
|
|
239
|
+
...signedManifest,
|
|
240
|
+
});
|
|
241
|
+
const addressNode = makeNode('address', address);
|
|
242
|
+
return rebuild(graph, [manifestNode, addressNode], [
|
|
243
|
+
makeEdge('manifests_as', manifestId, address),
|
|
244
|
+
]);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Add a signed manifest **revision** without collapsing other revisions.
|
|
248
|
+
*
|
|
249
|
+
* Creates:
|
|
250
|
+
* manifest (logical) refId = manifestId
|
|
251
|
+
* manifest (revision) refId = manifestEnvelopeId, data = { manifestId, manifestEnvelopeId, signedManifest }
|
|
252
|
+
* address resolved author/operator address
|
|
253
|
+
* manifests_as manifestId → address
|
|
254
|
+
* revision_of manifestEnvelopeId → manifestId
|
|
255
|
+
*/
|
|
256
|
+
function addManifestRevision(graph, signedManifest) {
|
|
257
|
+
const manifestId = (0, manifest_1.computeManifestId)(signedManifest.manifest);
|
|
258
|
+
const manifestEnvelopeId = (0, manifest_1.computeManifestEnvelopeId)(signedManifest);
|
|
259
|
+
const address = resolveManifestAddress(signedManifest);
|
|
260
|
+
const logicalNode = makeNode('manifest', manifestId, { manifestId });
|
|
261
|
+
const revisionNode = makeNode('manifest', manifestEnvelopeId, {
|
|
262
|
+
manifestId,
|
|
263
|
+
manifestEnvelopeId,
|
|
264
|
+
signedManifest,
|
|
265
|
+
});
|
|
266
|
+
const addressNode = makeNode('address', address);
|
|
267
|
+
return rebuild(graph, [logicalNode, revisionNode, addressNode], [
|
|
268
|
+
makeEdge('manifests_as', manifestId, address),
|
|
269
|
+
makeEdge('revision_of', manifestEnvelopeId, manifestId),
|
|
270
|
+
]);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Add a receipt-like node (payment, subscription, claim receipt) to the graph.
|
|
274
|
+
* If receipt.proofId is set, adds a 'supports' edge from the receipt to that proof.
|
|
275
|
+
*/
|
|
276
|
+
function addReceiptLike(graph, receipt) {
|
|
277
|
+
const { id, data, proofId } = receipt;
|
|
278
|
+
const receiptNode = makeNode('receipt', id, data);
|
|
279
|
+
const newEdges = [];
|
|
280
|
+
if (proofId !== undefined) {
|
|
281
|
+
newEdges.push(makeEdge('supports', id, proofId, proofId));
|
|
282
|
+
}
|
|
283
|
+
return rebuild(graph, [receiptNode], newEdges);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Add a standalone anchor node. If anchor.proofId is set, adds an 'anchored_to'
|
|
287
|
+
* edge from the proof to this anchor.
|
|
288
|
+
*/
|
|
289
|
+
function addAnchor(graph, anchor) {
|
|
290
|
+
const { hash, proofId, ...rest } = anchor;
|
|
291
|
+
const nodeData = { ...rest };
|
|
292
|
+
const anchorNode = makeNode('anchor', hash, Object.keys(nodeData).length > 0 ? nodeData : undefined);
|
|
293
|
+
const newEdges = [];
|
|
294
|
+
if (proofId !== undefined) {
|
|
295
|
+
newEdges.push(makeEdge('anchored_to', proofId, hash, proofId));
|
|
296
|
+
}
|
|
297
|
+
return rebuild(graph, [anchorNode], newEdges);
|
|
298
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @totemsdk/proofgraph
|
|
3
|
+
*
|
|
4
|
+
* Local deterministic proof relationship graph for Totem Edge.
|
|
5
|
+
*
|
|
6
|
+
* Indexes SignedProofs, SignedIdentityClaims, SignedManifests, identity
|
|
7
|
+
* documents, and custom evidence nodes into an immutable, queryable DAG
|
|
8
|
+
* keyed by a content-derived graphId. Pure package — no network, no DHT,
|
|
9
|
+
* no blockchain submission, no crypto reimplementation.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* const g0 = createProofGraph();
|
|
13
|
+
* const g1 = addProof(g0, signedProof);
|
|
14
|
+
* const result = verifyProofGraph(g1);
|
|
15
|
+
*/
|
|
16
|
+
export type { ProofGraphNodeType, ProofGraphEdgeType, ProofGraphNode, ProofGraphEdge, ProofGraph, ProofGraphVerifyResult, ProofGraphStoragePort, ReceiptLikeInput, AnchorInput, } from './types.js';
|
|
17
|
+
export { createDurableProofGraphStore, } from './durable-store.js';
|
|
18
|
+
export type { DurableProofGraphStore, DurableProofGraphStoreOptions, ProofGraphRecoveryReport, } from './durable-store.js';
|
|
19
|
+
export { createProofGraphEvidenceStore, assertEvidenceBinding, normalizeEvidenceHash, } from './evidence.js';
|
|
20
|
+
export type { ProofGraphEvidenceStore, ProofGraphEvidenceStoreOptions, ProofGraphEvidenceResult, EvidenceArtifactBinding, PutEvidenceOptions, } from './evidence.js';
|
|
21
|
+
export { toHex, canonicalJson, computeNodeId, computeEdgeId, computeProofGraphId, recomputeGraphId, } from './canonical.js';
|
|
22
|
+
export { createProofGraph, setGraphMetadata, buildEdge, addNode, addEdge, addIdentityDocument, addProof, addIdentityClaim, addManifest, addManifestRevision, addReceiptLike, addAnchor, } from './graph.js';
|
|
23
|
+
export { findNode, getEdgesFrom, getEdgesTo, getEdgesByType, getProofNodes, findProofsBySubject, findProofsByIssuer, findAnchorsForProof, findRevocations, findSupersessions, findConflicts, getEvidenceTrail, getProofLineage, resolveCurrentProofSet, getManifestRevisions, getManifestsForAddress, getEdgesBetween, reachableFrom, } from './query.js';
|
|
24
|
+
export { verifyProofGraph, verifyGraphProofs, } from './verify.js';
|
|
25
|
+
export { exportProofGraph, importProofGraph, } from './io.js';
|
|
26
|
+
export * from './replicated-evidence.js';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module @totemsdk/proofgraph
|
|
4
|
+
*
|
|
5
|
+
* Local deterministic proof relationship graph for Totem Edge.
|
|
6
|
+
*
|
|
7
|
+
* Indexes SignedProofs, SignedIdentityClaims, SignedManifests, identity
|
|
8
|
+
* documents, and custom evidence nodes into an immutable, queryable DAG
|
|
9
|
+
* keyed by a content-derived graphId. Pure package — no network, no DHT,
|
|
10
|
+
* no blockchain submission, no crypto reimplementation.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const g0 = createProofGraph();
|
|
14
|
+
* const g1 = addProof(g0, signedProof);
|
|
15
|
+
* const result = verifyProofGraph(g1);
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
29
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
exports.importProofGraph = exports.exportProofGraph = exports.verifyGraphProofs = exports.verifyProofGraph = exports.reachableFrom = exports.getEdgesBetween = exports.getManifestsForAddress = exports.getManifestRevisions = exports.resolveCurrentProofSet = exports.getProofLineage = exports.getEvidenceTrail = exports.findConflicts = exports.findSupersessions = exports.findRevocations = exports.findAnchorsForProof = exports.findProofsByIssuer = exports.findProofsBySubject = exports.getProofNodes = exports.getEdgesByType = exports.getEdgesTo = exports.getEdgesFrom = exports.findNode = exports.addAnchor = exports.addReceiptLike = exports.addManifestRevision = exports.addManifest = exports.addIdentityClaim = exports.addProof = exports.addIdentityDocument = exports.addEdge = exports.addNode = exports.buildEdge = exports.setGraphMetadata = exports.createProofGraph = exports.recomputeGraphId = exports.computeProofGraphId = exports.computeEdgeId = exports.computeNodeId = exports.canonicalJson = exports.toHex = exports.normalizeEvidenceHash = exports.assertEvidenceBinding = exports.createProofGraphEvidenceStore = exports.createDurableProofGraphStore = void 0;
|
|
33
|
+
var durable_store_js_1 = require("./durable-store.js");
|
|
34
|
+
Object.defineProperty(exports, "createDurableProofGraphStore", { enumerable: true, get: function () { return durable_store_js_1.createDurableProofGraphStore; } });
|
|
35
|
+
var evidence_js_1 = require("./evidence.js");
|
|
36
|
+
Object.defineProperty(exports, "createProofGraphEvidenceStore", { enumerable: true, get: function () { return evidence_js_1.createProofGraphEvidenceStore; } });
|
|
37
|
+
Object.defineProperty(exports, "assertEvidenceBinding", { enumerable: true, get: function () { return evidence_js_1.assertEvidenceBinding; } });
|
|
38
|
+
Object.defineProperty(exports, "normalizeEvidenceHash", { enumerable: true, get: function () { return evidence_js_1.normalizeEvidenceHash; } });
|
|
39
|
+
var canonical_js_1 = require("./canonical.js"); // canonicalJson / toHex re-exported from @totemsdk/proof
|
|
40
|
+
Object.defineProperty(exports, "toHex", { enumerable: true, get: function () { return canonical_js_1.toHex; } });
|
|
41
|
+
Object.defineProperty(exports, "canonicalJson", { enumerable: true, get: function () { return canonical_js_1.canonicalJson; } });
|
|
42
|
+
Object.defineProperty(exports, "computeNodeId", { enumerable: true, get: function () { return canonical_js_1.computeNodeId; } });
|
|
43
|
+
Object.defineProperty(exports, "computeEdgeId", { enumerable: true, get: function () { return canonical_js_1.computeEdgeId; } });
|
|
44
|
+
Object.defineProperty(exports, "computeProofGraphId", { enumerable: true, get: function () { return canonical_js_1.computeProofGraphId; } });
|
|
45
|
+
Object.defineProperty(exports, "recomputeGraphId", { enumerable: true, get: function () { return canonical_js_1.recomputeGraphId; } });
|
|
46
|
+
var graph_js_1 = require("./graph.js");
|
|
47
|
+
Object.defineProperty(exports, "createProofGraph", { enumerable: true, get: function () { return graph_js_1.createProofGraph; } });
|
|
48
|
+
Object.defineProperty(exports, "setGraphMetadata", { enumerable: true, get: function () { return graph_js_1.setGraphMetadata; } });
|
|
49
|
+
Object.defineProperty(exports, "buildEdge", { enumerable: true, get: function () { return graph_js_1.buildEdge; } });
|
|
50
|
+
Object.defineProperty(exports, "addNode", { enumerable: true, get: function () { return graph_js_1.addNode; } });
|
|
51
|
+
Object.defineProperty(exports, "addEdge", { enumerable: true, get: function () { return graph_js_1.addEdge; } });
|
|
52
|
+
Object.defineProperty(exports, "addIdentityDocument", { enumerable: true, get: function () { return graph_js_1.addIdentityDocument; } });
|
|
53
|
+
Object.defineProperty(exports, "addProof", { enumerable: true, get: function () { return graph_js_1.addProof; } });
|
|
54
|
+
Object.defineProperty(exports, "addIdentityClaim", { enumerable: true, get: function () { return graph_js_1.addIdentityClaim; } });
|
|
55
|
+
Object.defineProperty(exports, "addManifest", { enumerable: true, get: function () { return graph_js_1.addManifest; } });
|
|
56
|
+
Object.defineProperty(exports, "addManifestRevision", { enumerable: true, get: function () { return graph_js_1.addManifestRevision; } });
|
|
57
|
+
Object.defineProperty(exports, "addReceiptLike", { enumerable: true, get: function () { return graph_js_1.addReceiptLike; } });
|
|
58
|
+
Object.defineProperty(exports, "addAnchor", { enumerable: true, get: function () { return graph_js_1.addAnchor; } });
|
|
59
|
+
var query_js_1 = require("./query.js");
|
|
60
|
+
Object.defineProperty(exports, "findNode", { enumerable: true, get: function () { return query_js_1.findNode; } });
|
|
61
|
+
Object.defineProperty(exports, "getEdgesFrom", { enumerable: true, get: function () { return query_js_1.getEdgesFrom; } });
|
|
62
|
+
Object.defineProperty(exports, "getEdgesTo", { enumerable: true, get: function () { return query_js_1.getEdgesTo; } });
|
|
63
|
+
Object.defineProperty(exports, "getEdgesByType", { enumerable: true, get: function () { return query_js_1.getEdgesByType; } });
|
|
64
|
+
Object.defineProperty(exports, "getProofNodes", { enumerable: true, get: function () { return query_js_1.getProofNodes; } });
|
|
65
|
+
Object.defineProperty(exports, "findProofsBySubject", { enumerable: true, get: function () { return query_js_1.findProofsBySubject; } });
|
|
66
|
+
Object.defineProperty(exports, "findProofsByIssuer", { enumerable: true, get: function () { return query_js_1.findProofsByIssuer; } });
|
|
67
|
+
Object.defineProperty(exports, "findAnchorsForProof", { enumerable: true, get: function () { return query_js_1.findAnchorsForProof; } });
|
|
68
|
+
Object.defineProperty(exports, "findRevocations", { enumerable: true, get: function () { return query_js_1.findRevocations; } });
|
|
69
|
+
Object.defineProperty(exports, "findSupersessions", { enumerable: true, get: function () { return query_js_1.findSupersessions; } });
|
|
70
|
+
Object.defineProperty(exports, "findConflicts", { enumerable: true, get: function () { return query_js_1.findConflicts; } });
|
|
71
|
+
Object.defineProperty(exports, "getEvidenceTrail", { enumerable: true, get: function () { return query_js_1.getEvidenceTrail; } });
|
|
72
|
+
Object.defineProperty(exports, "getProofLineage", { enumerable: true, get: function () { return query_js_1.getProofLineage; } });
|
|
73
|
+
Object.defineProperty(exports, "resolveCurrentProofSet", { enumerable: true, get: function () { return query_js_1.resolveCurrentProofSet; } });
|
|
74
|
+
Object.defineProperty(exports, "getManifestRevisions", { enumerable: true, get: function () { return query_js_1.getManifestRevisions; } });
|
|
75
|
+
Object.defineProperty(exports, "getManifestsForAddress", { enumerable: true, get: function () { return query_js_1.getManifestsForAddress; } });
|
|
76
|
+
Object.defineProperty(exports, "getEdgesBetween", { enumerable: true, get: function () { return query_js_1.getEdgesBetween; } });
|
|
77
|
+
Object.defineProperty(exports, "reachableFrom", { enumerable: true, get: function () { return query_js_1.reachableFrom; } });
|
|
78
|
+
var verify_js_1 = require("./verify.js");
|
|
79
|
+
Object.defineProperty(exports, "verifyProofGraph", { enumerable: true, get: function () { return verify_js_1.verifyProofGraph; } });
|
|
80
|
+
Object.defineProperty(exports, "verifyGraphProofs", { enumerable: true, get: function () { return verify_js_1.verifyGraphProofs; } });
|
|
81
|
+
var io_js_1 = require("./io.js");
|
|
82
|
+
Object.defineProperty(exports, "exportProofGraph", { enumerable: true, get: function () { return io_js_1.exportProofGraph; } });
|
|
83
|
+
Object.defineProperty(exports, "importProofGraph", { enumerable: true, get: function () { return io_js_1.importProofGraph; } });
|
|
84
|
+
__exportStar(require("./replicated-evidence.js"), exports);
|
package/dist/cjs/io.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serialization helpers for ProofGraph.
|
|
3
|
+
*
|
|
4
|
+
* exportProofGraph: JSON-stringify the graph for storage or transport.
|
|
5
|
+
* importProofGraph: parse JSON, validate every node/edge, recompute graphId,
|
|
6
|
+
* and throw if verification fails.
|
|
7
|
+
*
|
|
8
|
+
* The graphId guards against silent corruption in transit. Node/edge
|
|
9
|
+
* validation prevents hostile or malformed input from entering the system.
|
|
10
|
+
*/
|
|
11
|
+
import type { ProofGraph } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Serialize a ProofGraph to a JSON string.
|
|
14
|
+
* The stored graphId was computed at mutation time and is included as-is.
|
|
15
|
+
*/
|
|
16
|
+
export declare function exportProofGraph(graph: ProofGraph): string;
|
|
17
|
+
/**
|
|
18
|
+
* Deserialize a ProofGraph from a JSON string.
|
|
19
|
+
*
|
|
20
|
+
* Validates every node and edge against structural constraints, then
|
|
21
|
+
* recomputes the graphId from nodes + edges. Throws if any constraint
|
|
22
|
+
* is violated or if the recomputed graphId does not match the stored value.
|
|
23
|
+
*
|
|
24
|
+
* @throws Error if parsing, validation, or graphId verification fails.
|
|
25
|
+
*/
|
|
26
|
+
export declare function importProofGraph(json: string): ProofGraph;
|
package/dist/cjs/io.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Serialization helpers for ProofGraph.
|
|
4
|
+
*
|
|
5
|
+
* exportProofGraph: JSON-stringify the graph for storage or transport.
|
|
6
|
+
* importProofGraph: parse JSON, validate every node/edge, recompute graphId,
|
|
7
|
+
* and throw if verification fails.
|
|
8
|
+
*
|
|
9
|
+
* The graphId guards against silent corruption in transit. Node/edge
|
|
10
|
+
* validation prevents hostile or malformed input from entering the system.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.exportProofGraph = exportProofGraph;
|
|
14
|
+
exports.importProofGraph = importProofGraph;
|
|
15
|
+
const canonical_js_1 = require("./canonical.js");
|
|
16
|
+
const VALID_NODE_TYPES = new Set([
|
|
17
|
+
'proof', 'identity', 'identity-claim', 'manifest', 'address',
|
|
18
|
+
'subject', 'evidence', 'anchor', 'receipt', 'payment', 'device',
|
|
19
|
+
'service', 'policy', 'custom',
|
|
20
|
+
]);
|
|
21
|
+
const VALID_EDGE_TYPES = new Set([
|
|
22
|
+
'proves', 'issued_by', 'signed_by', 'about', 'references',
|
|
23
|
+
'derived_from', 'supports', 'contradicts', 'supersedes', 'revokes',
|
|
24
|
+
'anchored_to', 'delegates_to', 'controls', 'depends_on',
|
|
25
|
+
'manifests_as', 'conflicts_with',
|
|
26
|
+
]);
|
|
27
|
+
const MAX_NODES = 10000;
|
|
28
|
+
const MAX_EDGES = 50000;
|
|
29
|
+
const MAX_STRING_LENGTH = 4096;
|
|
30
|
+
const MAX_DATA_DEPTH = 10;
|
|
31
|
+
const MAX_DATA_KEYS = 256;
|
|
32
|
+
/**
|
|
33
|
+
* Validate a single ProofGraphNode.
|
|
34
|
+
* Throws if the node violates structural constraints.
|
|
35
|
+
*/
|
|
36
|
+
function validateNode(node, index) {
|
|
37
|
+
if (!node || typeof node !== 'object') {
|
|
38
|
+
throw new Error(`importProofGraph: nodes[${index}] is not an object`);
|
|
39
|
+
}
|
|
40
|
+
const n = node;
|
|
41
|
+
if (typeof n.id !== 'string' || n.id.length === 0) {
|
|
42
|
+
throw new Error(`importProofGraph: nodes[${index}] missing or empty id`);
|
|
43
|
+
}
|
|
44
|
+
if (typeof n.refId !== 'string' || n.refId.length === 0) {
|
|
45
|
+
throw new Error(`importProofGraph: nodes[${index}] missing or empty refId`);
|
|
46
|
+
}
|
|
47
|
+
if (n.id.length > MAX_STRING_LENGTH) {
|
|
48
|
+
throw new Error(`importProofGraph: nodes[${index}].id exceeds ${MAX_STRING_LENGTH} chars`);
|
|
49
|
+
}
|
|
50
|
+
if (n.refId.length > MAX_STRING_LENGTH) {
|
|
51
|
+
throw new Error(`importProofGraph: nodes[${index}].refId exceeds ${MAX_STRING_LENGTH} chars`);
|
|
52
|
+
}
|
|
53
|
+
if (!VALID_NODE_TYPES.has(String(n.type))) {
|
|
54
|
+
throw new Error(`importProofGraph: nodes[${index}] invalid type "${String(n.type)}"`);
|
|
55
|
+
}
|
|
56
|
+
if (typeof n.createdAt !== 'number' || n.createdAt < 0 || !Number.isFinite(n.createdAt)) {
|
|
57
|
+
throw new Error(`importProofGraph: nodes[${index}] invalid or negative createdAt`);
|
|
58
|
+
}
|
|
59
|
+
if (n.data !== undefined && n.data !== null) {
|
|
60
|
+
if (typeof n.data !== 'object') {
|
|
61
|
+
throw new Error(`importProofGraph: nodes[${index}].data must be an object`);
|
|
62
|
+
}
|
|
63
|
+
const keys = Object.keys(n.data);
|
|
64
|
+
if (keys.length > MAX_DATA_KEYS) {
|
|
65
|
+
throw new Error(`importProofGraph: nodes[${index}].data exceeds ${MAX_DATA_KEYS} keys`);
|
|
66
|
+
}
|
|
67
|
+
checkDepth(n.data, 0, MAX_DATA_DEPTH, `nodes[${index}].data`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate a single ProofGraphEdge.
|
|
72
|
+
* Throws if the edge violates structural constraints.
|
|
73
|
+
*/
|
|
74
|
+
function validateEdge(edge, index) {
|
|
75
|
+
if (!edge || typeof edge !== 'object') {
|
|
76
|
+
throw new Error(`importProofGraph: edges[${index}] is not an object`);
|
|
77
|
+
}
|
|
78
|
+
const e = edge;
|
|
79
|
+
if (typeof e.id !== 'string' || e.id.length === 0) {
|
|
80
|
+
throw new Error(`importProofGraph: edges[${index}] missing or empty id`);
|
|
81
|
+
}
|
|
82
|
+
if (typeof e.from !== 'string' || e.from.length === 0) {
|
|
83
|
+
throw new Error(`importProofGraph: edges[${index}] missing or empty from`);
|
|
84
|
+
}
|
|
85
|
+
if (typeof e.to !== 'string' || e.to.length === 0) {
|
|
86
|
+
throw new Error(`importProofGraph: edges[${index}] missing or empty to`);
|
|
87
|
+
}
|
|
88
|
+
if (e.id.length > MAX_STRING_LENGTH || e.from.length > MAX_STRING_LENGTH || e.to.length > MAX_STRING_LENGTH) {
|
|
89
|
+
throw new Error(`importProofGraph: edges[${index}] string field exceeds ${MAX_STRING_LENGTH} chars`);
|
|
90
|
+
}
|
|
91
|
+
if (!VALID_EDGE_TYPES.has(String(e.type))) {
|
|
92
|
+
throw new Error(`importProofGraph: edges[${index}] invalid type "${String(e.type)}"`);
|
|
93
|
+
}
|
|
94
|
+
if (e.proofId !== undefined && typeof e.proofId !== 'string') {
|
|
95
|
+
throw new Error(`importProofGraph: edges[${index}].proofId must be a string`);
|
|
96
|
+
}
|
|
97
|
+
if (e.data !== undefined && e.data !== null) {
|
|
98
|
+
if (typeof e.data !== 'object') {
|
|
99
|
+
throw new Error(`importProofGraph: edges[${index}].data must be an object`);
|
|
100
|
+
}
|
|
101
|
+
checkDepth(e.data, 0, MAX_DATA_DEPTH, `edges[${index}].data`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Recursive depth check on nested data objects to prevent deep-object attacks.
|
|
106
|
+
*/
|
|
107
|
+
function checkDepth(obj, depth, maxDepth, path) {
|
|
108
|
+
if (depth > maxDepth) {
|
|
109
|
+
throw new Error(`importProofGraph: ${path} exceeds max nesting depth of ${maxDepth}`);
|
|
110
|
+
}
|
|
111
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
112
|
+
if (typeof key === 'string' && key.length > MAX_STRING_LENGTH) {
|
|
113
|
+
throw new Error(`importProofGraph: ${path} key exceeds ${MAX_STRING_LENGTH} chars`);
|
|
114
|
+
}
|
|
115
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Uint8Array)) {
|
|
116
|
+
checkDepth(value, depth + 1, maxDepth, `${path}.${key}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Serialize a ProofGraph to a JSON string.
|
|
122
|
+
* The stored graphId was computed at mutation time and is included as-is.
|
|
123
|
+
*/
|
|
124
|
+
function exportProofGraph(graph) {
|
|
125
|
+
return JSON.stringify(graph);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Deserialize a ProofGraph from a JSON string.
|
|
129
|
+
*
|
|
130
|
+
* Validates every node and edge against structural constraints, then
|
|
131
|
+
* recomputes the graphId from nodes + edges. Throws if any constraint
|
|
132
|
+
* is violated or if the recomputed graphId does not match the stored value.
|
|
133
|
+
*
|
|
134
|
+
* @throws Error if parsing, validation, or graphId verification fails.
|
|
135
|
+
*/
|
|
136
|
+
function importProofGraph(json) {
|
|
137
|
+
let parsed;
|
|
138
|
+
try {
|
|
139
|
+
parsed = JSON.parse(json);
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
throw new Error(`importProofGraph: invalid JSON — ${err.message}`);
|
|
143
|
+
}
|
|
144
|
+
const graph = parsed;
|
|
145
|
+
if (!graph || typeof graph !== 'object') {
|
|
146
|
+
throw new Error('importProofGraph: parsed value is not an object');
|
|
147
|
+
}
|
|
148
|
+
if (!Array.isArray(graph.nodes) || !Array.isArray(graph.edges)) {
|
|
149
|
+
throw new Error('importProofGraph: missing nodes or edges arrays');
|
|
150
|
+
}
|
|
151
|
+
if (graph.nodes.length > MAX_NODES) {
|
|
152
|
+
throw new Error(`importProofGraph: node count ${graph.nodes.length} exceeds limit ${MAX_NODES}`);
|
|
153
|
+
}
|
|
154
|
+
if (graph.edges.length > MAX_EDGES) {
|
|
155
|
+
throw new Error(`importProofGraph: edge count ${graph.edges.length} exceeds limit ${MAX_EDGES}`);
|
|
156
|
+
}
|
|
157
|
+
// Validate every node and edge
|
|
158
|
+
for (let i = 0; i < graph.nodes.length; i++) {
|
|
159
|
+
validateNode(graph.nodes[i], i);
|
|
160
|
+
}
|
|
161
|
+
for (let i = 0; i < graph.edges.length; i++) {
|
|
162
|
+
validateEdge(graph.edges[i], i);
|
|
163
|
+
}
|
|
164
|
+
// Recompute and verify graphId
|
|
165
|
+
const originalId = typeof graph.graphId === 'string' ? graph.graphId : '';
|
|
166
|
+
const recomputed = (0, canonical_js_1.recomputeGraphId)(graph);
|
|
167
|
+
// If a stored graphId exists, verify it matches
|
|
168
|
+
if (originalId !== '' && recomputed !== originalId) {
|
|
169
|
+
throw new Error(`importProofGraph: graphId mismatch — stored="${originalId}" recomputed="${recomputed}"`);
|
|
170
|
+
}
|
|
171
|
+
// Return with graphId set to the recomputed value for consistency
|
|
172
|
+
return { ...graph, graphId: recomputed };
|
|
173
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|