@totemsdk/proofgraph 1.0.0 → 1.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 +202 -21
- package/NOTICE +60 -0
- package/README.md +1 -1
- 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.d.ts +50 -0
- package/dist/durable-store.js +175 -0
- package/dist/evidence.d.ts +89 -0
- package/dist/evidence.js +125 -0
- package/dist/graph.d.ts +11 -0
- package/dist/graph.js +49 -33
- package/dist/index.d.ts +7 -2
- package/dist/index.js +8 -46
- package/dist/io.js +4 -8
- package/dist/query.d.ts +4 -0
- package/dist/query.js +28 -36
- 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 +22 -14
- 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,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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query helpers for ProofGraph — pure read-only utilities.
|
|
3
|
+
*
|
|
4
|
+
* All functions receive a ProofGraph and return data without mutating the graph.
|
|
5
|
+
* Function names match the @totemsdk/proofgraph public API spec exactly.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProofGraph, ProofGraphNode, ProofGraphEdge, ProofGraphEdgeType } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Find a node by its composed node ID (type:refId) or by refId alone.
|
|
10
|
+
*/
|
|
11
|
+
export declare function findNode(graph: ProofGraph, id: string): ProofGraphNode | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Return all outgoing edges from a node (identified by node ID or refId).
|
|
14
|
+
*/
|
|
15
|
+
export declare function getEdgesFrom(graph: ProofGraph, nodeIdOrRefId: string): ProofGraphEdge[];
|
|
16
|
+
/**
|
|
17
|
+
* Return all incoming edges to a node (identified by node ID or refId).
|
|
18
|
+
*/
|
|
19
|
+
export declare function getEdgesTo(graph: ProofGraph, nodeIdOrRefId: string): ProofGraphEdge[];
|
|
20
|
+
/**
|
|
21
|
+
* Return all edges of a given type.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getEdgesByType(graph: ProofGraph, type: ProofGraphEdgeType): ProofGraphEdge[];
|
|
24
|
+
/**
|
|
25
|
+
* Return all proof nodes in the graph.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getProofNodes(graph: ProofGraph): ProofGraphNode[];
|
|
28
|
+
/**
|
|
29
|
+
* Find all 'proof' nodes connected to a subject via 'about' OR 'proves' edges.
|
|
30
|
+
*/
|
|
31
|
+
export declare function findProofsBySubject(graph: ProofGraph, subjectId: string): ProofGraphNode[];
|
|
32
|
+
/**
|
|
33
|
+
* Find all 'proof' nodes issued by a given address (via 'issued_by' edges).
|
|
34
|
+
*/
|
|
35
|
+
export declare function findProofsByIssuer(graph: ProofGraph, issuerId: string): ProofGraphNode[];
|
|
36
|
+
/**
|
|
37
|
+
* Find all 'anchor' nodes linked to a proof via 'anchored_to' edges.
|
|
38
|
+
*/
|
|
39
|
+
export declare function findAnchorsForProof(graph: ProofGraph, proofId: string): ProofGraphNode[];
|
|
40
|
+
/**
|
|
41
|
+
* Find all 'revokes' edges whose target is the given proof node.
|
|
42
|
+
*/
|
|
43
|
+
export declare function findRevocations(graph: ProofGraph, proofId: string): ProofGraphEdge[];
|
|
44
|
+
/**
|
|
45
|
+
* Find all 'supersedes' edges whose target is the given proof node.
|
|
46
|
+
*/
|
|
47
|
+
export declare function findSupersessions(graph: ProofGraph, proofId: string): ProofGraphEdge[];
|
|
48
|
+
/**
|
|
49
|
+
* Find all 'conflicts_with' edges involving the given proof node (in either direction).
|
|
50
|
+
*/
|
|
51
|
+
export declare function findConflicts(graph: ProofGraph, proofId: string): ProofGraphEdge[];
|
|
52
|
+
/**
|
|
53
|
+
* Traverse 'references' edges from a proof to its evidence nodes.
|
|
54
|
+
* Returns nodes in insertion order (the order edges were added, which matches
|
|
55
|
+
* the original evidence array order from addProof).
|
|
56
|
+
*/
|
|
57
|
+
export declare function getEvidenceTrail(graph: ProofGraph, proofId: string): ProofGraphNode[];
|
|
58
|
+
/**
|
|
59
|
+
* Recursively traverse 'derived_from' edges from a proof node.
|
|
60
|
+
* Returns the ordered chain of ancestor proof nodes (closest ancestor first).
|
|
61
|
+
* Terminates on cycle detection.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getProofLineage(graph: ProofGraph, proofId: string, _visited?: Set<string>): ProofGraphNode[];
|
|
64
|
+
/**
|
|
65
|
+
* Return all proof nodes that are NOT the target of any 'revokes' or 'supersedes' edge.
|
|
66
|
+
* These are the current / active proofs in the graph.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveCurrentProofSet(graph: ProofGraph): ProofGraphNode[];
|
|
69
|
+
/**
|
|
70
|
+
* Return all manifest nodes linked to a given address via 'manifests_as' edges.
|
|
71
|
+
*/
|
|
72
|
+
export declare function getManifestsForAddress(graph: ProofGraph, address: string): ProofGraphNode[];
|
|
73
|
+
/**
|
|
74
|
+
* Return all content-addressed revisions of a logical manifest, ordered by envelope ID.
|
|
75
|
+
*/
|
|
76
|
+
export declare function getManifestRevisions(graph: ProofGraph, manifestId: string): ProofGraphNode[];
|
|
77
|
+
/**
|
|
78
|
+
* Return all edges between two nodes (in either direction).
|
|
79
|
+
*/
|
|
80
|
+
export declare function getEdgesBetween(graph: ProofGraph, refIdA: string, refIdB: string): ProofGraphEdge[];
|
|
81
|
+
/**
|
|
82
|
+
* Return the set of all node refIds reachable from a given node via directed edges.
|
|
83
|
+
* Includes the start node itself.
|
|
84
|
+
*/
|
|
85
|
+
export declare function reachableFrom(graph: ProofGraph, startRefId: string, _visited?: Set<string>): Set<string>;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Query helpers for ProofGraph — pure read-only utilities.
|
|
4
|
+
*
|
|
5
|
+
* All functions receive a ProofGraph and return data without mutating the graph.
|
|
6
|
+
* Function names match the @totemsdk/proofgraph public API spec exactly.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.findNode = findNode;
|
|
10
|
+
exports.getEdgesFrom = getEdgesFrom;
|
|
11
|
+
exports.getEdgesTo = getEdgesTo;
|
|
12
|
+
exports.getEdgesByType = getEdgesByType;
|
|
13
|
+
exports.getProofNodes = getProofNodes;
|
|
14
|
+
exports.findProofsBySubject = findProofsBySubject;
|
|
15
|
+
exports.findProofsByIssuer = findProofsByIssuer;
|
|
16
|
+
exports.findAnchorsForProof = findAnchorsForProof;
|
|
17
|
+
exports.findRevocations = findRevocations;
|
|
18
|
+
exports.findSupersessions = findSupersessions;
|
|
19
|
+
exports.findConflicts = findConflicts;
|
|
20
|
+
exports.getEvidenceTrail = getEvidenceTrail;
|
|
21
|
+
exports.getProofLineage = getProofLineage;
|
|
22
|
+
exports.resolveCurrentProofSet = resolveCurrentProofSet;
|
|
23
|
+
exports.getManifestsForAddress = getManifestsForAddress;
|
|
24
|
+
exports.getManifestRevisions = getManifestRevisions;
|
|
25
|
+
exports.getEdgesBetween = getEdgesBetween;
|
|
26
|
+
exports.reachableFrom = reachableFrom;
|
|
27
|
+
/**
|
|
28
|
+
* Find a node by its composed node ID (type:refId) or by refId alone.
|
|
29
|
+
*/
|
|
30
|
+
function findNode(graph, id) {
|
|
31
|
+
return graph.nodes.find((n) => n.id === id || n.refId === id);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Return all outgoing edges from a node (identified by node ID or refId).
|
|
35
|
+
*/
|
|
36
|
+
function getEdgesFrom(graph, nodeIdOrRefId) {
|
|
37
|
+
const node = findNode(graph, nodeIdOrRefId);
|
|
38
|
+
if (!node)
|
|
39
|
+
return [];
|
|
40
|
+
return graph.edges.filter((e) => e.from === node.refId);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Return all incoming edges to a node (identified by node ID or refId).
|
|
44
|
+
*/
|
|
45
|
+
function getEdgesTo(graph, nodeIdOrRefId) {
|
|
46
|
+
const node = findNode(graph, nodeIdOrRefId);
|
|
47
|
+
if (!node)
|
|
48
|
+
return [];
|
|
49
|
+
return graph.edges.filter((e) => e.to === node.refId);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Return all edges of a given type.
|
|
53
|
+
*/
|
|
54
|
+
function getEdgesByType(graph, type) {
|
|
55
|
+
return graph.edges.filter((e) => e.type === type);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Return all proof nodes in the graph.
|
|
59
|
+
*/
|
|
60
|
+
function getProofNodes(graph) {
|
|
61
|
+
return graph.nodes.filter((n) => n.type === 'proof');
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Find all 'proof' nodes connected to a subject via 'about' OR 'proves' edges.
|
|
65
|
+
*/
|
|
66
|
+
function findProofsBySubject(graph, subjectId) {
|
|
67
|
+
const relevantEdges = graph.edges.filter((e) => (e.type === 'about' || e.type === 'proves') && e.to === subjectId);
|
|
68
|
+
const proofRefIds = new Set(relevantEdges.map((e) => e.from));
|
|
69
|
+
return graph.nodes.filter((n) => proofRefIds.has(n.refId) && n.type === 'proof');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Find all 'proof' nodes issued by a given address (via 'issued_by' edges).
|
|
73
|
+
*/
|
|
74
|
+
function findProofsByIssuer(graph, issuerId) {
|
|
75
|
+
const issuedEdges = graph.edges.filter((e) => e.type === 'issued_by' && e.to === issuerId);
|
|
76
|
+
const proofRefIds = new Set(issuedEdges.map((e) => e.from));
|
|
77
|
+
return graph.nodes.filter((n) => proofRefIds.has(n.refId) && n.type === 'proof');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Find all 'anchor' nodes linked to a proof via 'anchored_to' edges.
|
|
81
|
+
*/
|
|
82
|
+
function findAnchorsForProof(graph, proofId) {
|
|
83
|
+
const anchoredEdges = graph.edges.filter((e) => e.type === 'anchored_to' && e.from === proofId);
|
|
84
|
+
const anchorRefIds = new Set(anchoredEdges.map((e) => e.to));
|
|
85
|
+
return graph.nodes.filter((n) => anchorRefIds.has(n.refId) && n.type === 'anchor');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Find all 'revokes' edges whose target is the given proof node.
|
|
89
|
+
*/
|
|
90
|
+
function findRevocations(graph, proofId) {
|
|
91
|
+
return graph.edges.filter((e) => e.type === 'revokes' && e.to === proofId);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Find all 'supersedes' edges whose target is the given proof node.
|
|
95
|
+
*/
|
|
96
|
+
function findSupersessions(graph, proofId) {
|
|
97
|
+
return graph.edges.filter((e) => e.type === 'supersedes' && e.to === proofId);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Find all 'conflicts_with' edges involving the given proof node (in either direction).
|
|
101
|
+
*/
|
|
102
|
+
function findConflicts(graph, proofId) {
|
|
103
|
+
return graph.edges.filter((e) => e.type === 'conflicts_with' &&
|
|
104
|
+
(e.from === proofId || e.to === proofId));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Traverse 'references' edges from a proof to its evidence nodes.
|
|
108
|
+
* Returns nodes in insertion order (the order edges were added, which matches
|
|
109
|
+
* the original evidence array order from addProof).
|
|
110
|
+
*/
|
|
111
|
+
function getEvidenceTrail(graph, proofId) {
|
|
112
|
+
const refEdges = graph.edges.filter((e) => e.type === 'references' && e.from === proofId);
|
|
113
|
+
return refEdges
|
|
114
|
+
.map((e) => graph.nodes.find((n) => n.refId === e.to && n.type === 'evidence'))
|
|
115
|
+
.filter((n) => n !== undefined);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Recursively traverse 'derived_from' edges from a proof node.
|
|
119
|
+
* Returns the ordered chain of ancestor proof nodes (closest ancestor first).
|
|
120
|
+
* Terminates on cycle detection.
|
|
121
|
+
*/
|
|
122
|
+
function getProofLineage(graph, proofId, _visited = new Set()) {
|
|
123
|
+
if (_visited.has(proofId))
|
|
124
|
+
return [];
|
|
125
|
+
_visited.add(proofId);
|
|
126
|
+
const derivedEdges = graph.edges.filter((e) => e.type === 'derived_from' && e.from === proofId);
|
|
127
|
+
const result = [];
|
|
128
|
+
for (const edge of derivedEdges) {
|
|
129
|
+
const node = graph.nodes.find((n) => n.refId === edge.to);
|
|
130
|
+
if (node) {
|
|
131
|
+
result.push(node);
|
|
132
|
+
result.push(...getProofLineage(graph, edge.to, _visited));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Return all proof nodes that are NOT the target of any 'revokes' or 'supersedes' edge.
|
|
139
|
+
* These are the current / active proofs in the graph.
|
|
140
|
+
*/
|
|
141
|
+
function resolveCurrentProofSet(graph) {
|
|
142
|
+
const supersededOrRevoked = new Set();
|
|
143
|
+
for (const edge of graph.edges) {
|
|
144
|
+
if (edge.type === 'revokes' || edge.type === 'supersedes') {
|
|
145
|
+
supersededOrRevoked.add(edge.to);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return graph.nodes.filter((n) => n.type === 'proof' && !supersededOrRevoked.has(n.refId));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Return all manifest nodes linked to a given address via 'manifests_as' edges.
|
|
152
|
+
*/
|
|
153
|
+
function getManifestsForAddress(graph, address) {
|
|
154
|
+
const manifestEdges = graph.edges.filter((e) => e.type === 'manifests_as' && e.to === address);
|
|
155
|
+
const manifestRefIds = new Set(manifestEdges.map((e) => e.from));
|
|
156
|
+
return graph.nodes.filter((n) => manifestRefIds.has(n.refId) && n.type === 'manifest');
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Return all content-addressed revisions of a logical manifest, ordered by envelope ID.
|
|
160
|
+
*/
|
|
161
|
+
function getManifestRevisions(graph, manifestId) {
|
|
162
|
+
const revisionRefs = new Set(graph.edges
|
|
163
|
+
.filter((edge) => edge.type === 'revision_of' && edge.to === manifestId)
|
|
164
|
+
.map((edge) => edge.from));
|
|
165
|
+
return graph.nodes
|
|
166
|
+
.filter((node) => node.type === 'manifest' && revisionRefs.has(node.refId))
|
|
167
|
+
.sort((a, b) => a.refId.localeCompare(b.refId));
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Return all edges between two nodes (in either direction).
|
|
171
|
+
*/
|
|
172
|
+
function getEdgesBetween(graph, refIdA, refIdB) {
|
|
173
|
+
return graph.edges.filter((e) => (e.from === refIdA && e.to === refIdB) ||
|
|
174
|
+
(e.from === refIdB && e.to === refIdA));
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Return the set of all node refIds reachable from a given node via directed edges.
|
|
178
|
+
* Includes the start node itself.
|
|
179
|
+
*/
|
|
180
|
+
function reachableFrom(graph, startRefId, _visited = new Set()) {
|
|
181
|
+
if (_visited.has(startRefId))
|
|
182
|
+
return _visited;
|
|
183
|
+
_visited.add(startRefId);
|
|
184
|
+
const outgoing = graph.edges.filter((e) => e.from === startRefId);
|
|
185
|
+
for (const edge of outgoing) {
|
|
186
|
+
reachableFrom(graph, edge.to, _visited);
|
|
187
|
+
}
|
|
188
|
+
return _visited;
|
|
189
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC-057 Phase 4 — replicated proofgraph evidence adapter.
|
|
3
|
+
*
|
|
4
|
+
* Keeps the authoritative proofgraph evidence store local while allowing a
|
|
5
|
+
* replicated index to locate the same digest-verified artifacts on other
|
|
6
|
+
* peers. The replicated index is never trusted for bytes: every read
|
|
7
|
+
* re-verifies the artifact digest.
|
|
8
|
+
*/
|
|
9
|
+
import type { ArtifactRef, ArtifactStore } from '@totemsdk/storage/artifacts';
|
|
10
|
+
import type { ProofGraph } from './types.js';
|
|
11
|
+
export interface ReplicatedEvidenceIndexEntry {
|
|
12
|
+
readonly nodeId: string;
|
|
13
|
+
readonly ref: ArtifactRef;
|
|
14
|
+
readonly contentHash: string;
|
|
15
|
+
readonly storedAt: number;
|
|
16
|
+
}
|
|
17
|
+
export interface ReplicatedEvidenceIndexPort {
|
|
18
|
+
get(key: string): Promise<unknown | null>;
|
|
19
|
+
put(key: string, value: unknown): Promise<void>;
|
|
20
|
+
list?(prefix?: string): AsyncIterable<{
|
|
21
|
+
key: string;
|
|
22
|
+
value: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
25
|
+
export interface ReplicatedEvidenceRead {
|
|
26
|
+
readonly nodeId: string;
|
|
27
|
+
readonly status: 'ok' | 'not-found' | 'corrupt' | 'unavailable';
|
|
28
|
+
readonly ref?: ArtifactRef;
|
|
29
|
+
readonly bytes?: Uint8Array;
|
|
30
|
+
readonly message?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ReplicatedProofGraphEvidenceStore {
|
|
33
|
+
putEvidence(graph: ProofGraph, bytesFor: (nodeId: string) => Uint8Array | undefined): Promise<ArtifactRef[]>;
|
|
34
|
+
getEvidence(nodeId: string): Promise<ReplicatedEvidenceRead>;
|
|
35
|
+
verifyEvidence(nodeId: string): Promise<boolean>;
|
|
36
|
+
listEvidence(): AsyncIterable<ReplicatedEvidenceIndexEntry>;
|
|
37
|
+
}
|
|
38
|
+
export declare function createReplicatedProofGraphEvidenceStore(options: {
|
|
39
|
+
artifacts: ArtifactStore;
|
|
40
|
+
index: ReplicatedEvidenceIndexPort;
|
|
41
|
+
namespace?: string;
|
|
42
|
+
}): ReplicatedProofGraphEvidenceStore;
|