@factoidal/core 0.20.0 → 0.21.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/CHANGELOG.md +49 -0
- package/README.md +38 -2
- package/authz/server.mjs +23 -2
- package/bin/engine.mjs +22 -1
- package/bin/factoidal.mjs +710 -38
- package/bin/pack-host.mjs +5 -0
- package/bin/serve.mjs +19 -3
- package/browser.d.ts +10 -0
- package/browser.js +12 -0
- package/index.d.ts +248 -9
- package/index.mjs +15 -0
- package/l4-assets/l4factoidal.js +1 -1
- package/l4-assets/l4factoidal.wasm +0 -0
- package/l4-assets/version.json +6 -6
- package/lib/api.mjs +236 -12
- package/lib/browser-engine.mjs +28 -1
- package/lib/cid-node.mjs +77 -0
- package/lib/cid.mjs +146 -0
- package/lib/cipher-host.mjs +126 -0
- package/lib/engine-integrity.mjs +56 -0
- package/lib/nodes.mjs +234 -11
- package/lib/sbm11.mjs +14 -1
- package/lib/version.mjs +1 -1
- package/lws/README.md +9 -0
- package/lws/client.mjs +19 -2
- package/lws/persist.mjs +169 -0
- package/lws/server.mjs +82 -29
- package/package.json +2 -1
- package/solid/server/index.mjs +79 -13
- package/webdav/server.mjs +154 -25
- package/xmpp/client.mjs +332 -0
- package/xmpp/proxy.mjs +114 -0
package/bin/pack-host.mjs
CHANGED
|
@@ -363,6 +363,11 @@ export async function denoReexec (options) {
|
|
|
363
363
|
return null
|
|
364
364
|
}
|
|
365
365
|
if (granted.indexOf('run') < 0 || granted.indexOf('read') < 0) return null
|
|
366
|
+
// A `deno compile` executable is not the deno command: given `run ...` it
|
|
367
|
+
// reads `run` as a factoidal command (found 2026-10-28, building the
|
|
368
|
+
// single-file executables of docs/designissues/2026-10-28-single-file-app.md).
|
|
369
|
+
// It packs in process instead.
|
|
370
|
+
if (!/^deno(\.exe)?$/i.test(Deno.execPath().split(/[\\/]/).pop())) return null
|
|
366
371
|
const main = Deno.mainModule.startsWith('file://')
|
|
367
372
|
? fileUrlToPath(Deno.mainModule)
|
|
368
373
|
: Deno.mainModule
|
package/bin/serve.mjs
CHANGED
|
@@ -147,6 +147,8 @@ export async function openServedStore (root, options = {}) {
|
|
|
147
147
|
const config = {}
|
|
148
148
|
if (typeof options.queryPath === 'string') config.queryPath = options.queryPath
|
|
149
149
|
if (typeof options.gspPath === 'string') config.gspPath = options.gspPath
|
|
150
|
+
// The Host and Origin guard (issue 1124): passed unread; the engine decides.
|
|
151
|
+
if (options.localGuard !== undefined && options.localGuard !== null) config.localGuard = options.localGuard
|
|
150
152
|
const info = engine.callBlobIO('storeServeOpen',
|
|
151
153
|
[manifestHex, JSON.stringify(artifacts), JSON.stringify(state), JSON.stringify(config)],
|
|
152
154
|
concatenate(chunks)).envelope
|
|
@@ -233,6 +235,8 @@ export async function openServedTdb2 (root, options = {}) {
|
|
|
233
235
|
const config = {}
|
|
234
236
|
if (typeof options.queryPath === 'string') config.queryPath = options.queryPath
|
|
235
237
|
if (typeof options.gspPath === 'string') config.gspPath = options.gspPath
|
|
238
|
+
// The Host and Origin guard (issue 1124): passed unread; the engine decides.
|
|
239
|
+
if (options.localGuard !== undefined && options.localGuard !== null) config.localGuard = options.localGuard
|
|
236
240
|
const info = engine.callBlobIO('tdb2ServeOpen',
|
|
237
241
|
[JSON.stringify(files), JSON.stringify(config)], concatenate(chunks)).envelope
|
|
238
242
|
const handle = info.handle
|
|
@@ -343,9 +347,22 @@ function serveConnection (served, socket, onError) {
|
|
|
343
347
|
*/
|
|
344
348
|
export async function listen (root, options = {}) {
|
|
345
349
|
const net = await import('node:net')
|
|
350
|
+
const host = typeof options.host === 'string' ? options.host : '127.0.0.1'
|
|
351
|
+
// `factoidal serve` has no authentication: the engine answers only the
|
|
352
|
+
// listener's own names and refuses writes from another origin
|
|
353
|
+
// (https://github.com/danbri/factoidal/issues/1124). Data for its check.
|
|
354
|
+
const os = await import('node:os')
|
|
355
|
+
let addresses = []
|
|
356
|
+
try { addresses = Object.values(os.networkInterfaces()).flat().filter(Boolean).map((i) => i.address) } catch (_error) { addresses = [] }
|
|
357
|
+
const localGuard = {
|
|
358
|
+
host,
|
|
359
|
+
addresses,
|
|
360
|
+
...(Array.isArray(options.allowHosts) ? { allowHosts: options.allowHosts } : {}),
|
|
361
|
+
...(Array.isArray(options.allowOrigins) ? { allowOrigins: options.allowOrigins } : {})
|
|
362
|
+
}
|
|
346
363
|
const served = options.tdb2 === true
|
|
347
|
-
? await openServedTdb2(root, options)
|
|
348
|
-
: await openServedStore(root, options)
|
|
364
|
+
? await openServedTdb2(root, { ...options, localGuard })
|
|
365
|
+
: await openServedStore(root, { ...options, localGuard })
|
|
349
366
|
const onError = typeof options.onError === 'function'
|
|
350
367
|
? options.onError
|
|
351
368
|
: (error) => { console.error(`factoidal serve: ${error && error.message ? error.message : error}`) }
|
|
@@ -356,7 +373,6 @@ export async function listen (root, options = {}) {
|
|
|
356
373
|
serveConnection(served, socket, onError)
|
|
357
374
|
})
|
|
358
375
|
const port = typeof options.port === 'number' ? options.port : 0
|
|
359
|
-
const host = typeof options.host === 'string' ? options.host : '127.0.0.1'
|
|
360
376
|
await new Promise((resolve, reject) => {
|
|
361
377
|
server.once('error', reject)
|
|
362
378
|
server.listen(port, host, resolve)
|
package/browser.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type {
|
|
|
14
14
|
Sbm11Reader, Sbm11Answer, Sbm11Store, Sbm11ReadEvidence, Sbm11Transport,
|
|
15
15
|
LiteralValueData, LiteralValueResult,
|
|
16
16
|
ExplainResult, StageInfo, EvidenceRecord, Wire, FactoidalNode, Pipeline, RunResult, RunOptions,
|
|
17
|
+
NodePort, GraphSource, GraphSpec, GraphIssue, GraphCheck, FactoidalGraph, GraphRunResult,
|
|
17
18
|
} from './index';
|
|
18
19
|
|
|
19
20
|
export {
|
|
@@ -26,6 +27,7 @@ export {
|
|
|
26
27
|
canonicalHash,
|
|
27
28
|
asDefaultGraph,
|
|
28
29
|
isomorphic,
|
|
30
|
+
datasetMerge,
|
|
29
31
|
fromQuads,
|
|
30
32
|
literalValue,
|
|
31
33
|
isValidLiteral,
|
|
@@ -42,6 +44,7 @@ export {
|
|
|
42
44
|
memberOrdinal,
|
|
43
45
|
openDataset,
|
|
44
46
|
closure,
|
|
47
|
+
sparqlRlInfer,
|
|
45
48
|
formats,
|
|
46
49
|
queryRaw,
|
|
47
50
|
queryHdt,
|
|
@@ -74,6 +77,7 @@ export {
|
|
|
74
77
|
stages,
|
|
75
78
|
node,
|
|
76
79
|
pipe,
|
|
80
|
+
graph,
|
|
77
81
|
run,
|
|
78
82
|
rdfsPlusClosure,
|
|
79
83
|
rhoDfClosure,
|
|
@@ -107,12 +111,18 @@ export {
|
|
|
107
111
|
vcEd25519SecretToPublic,
|
|
108
112
|
vcEd25519Sign,
|
|
109
113
|
vcEd25519Verify,
|
|
114
|
+
xmlDecrypt,
|
|
115
|
+
xmlEncrypt,
|
|
116
|
+
jweDecrypt,
|
|
117
|
+
jweEncrypt,
|
|
110
118
|
vcEddsaCreateFromCanonical,
|
|
111
119
|
vcEddsaVerifyFromCanonical,
|
|
112
120
|
vcCheckCredential,
|
|
113
121
|
vcCheckCredentialSubject,
|
|
114
122
|
vcCheckNoDataLoss,
|
|
115
123
|
vcCheckRelatedResourceDigests,
|
|
124
|
+
cidValidate,
|
|
125
|
+
cidRetrieveVerificationMethod,
|
|
116
126
|
didKeyResolve,
|
|
117
127
|
capabilities,
|
|
118
128
|
Dataset,
|
package/browser.js
CHANGED
|
@@ -85,6 +85,7 @@ export const graphs = api.graphs;
|
|
|
85
85
|
export const canonicalHash = api.canonicalHash;
|
|
86
86
|
export const asDefaultGraph = api.asDefaultGraph;
|
|
87
87
|
export const isomorphic = api.isomorphic;
|
|
88
|
+
export const datasetMerge = api.datasetMerge;
|
|
88
89
|
export const fromQuads = api.fromQuads;
|
|
89
90
|
// Literal values (https://github.com/danbri/factoidal/issues/1051): synchronous
|
|
90
91
|
// after the engine is loaded.
|
|
@@ -103,6 +104,7 @@ export const memberIri = api.memberIri;
|
|
|
103
104
|
export const memberOrdinal = api.memberOrdinal;
|
|
104
105
|
export const openDataset = api.openDataset;
|
|
105
106
|
export const closure = api.closure;
|
|
107
|
+
export const sparqlRlInfer = api.sparqlRlInfer;
|
|
106
108
|
export const formats = api.formats;
|
|
107
109
|
export const queryRaw = api.queryRaw;
|
|
108
110
|
export const queryHdt = api.queryHdt;
|
|
@@ -136,6 +138,7 @@ export const explain = api.explain;
|
|
|
136
138
|
export const stages = api.stages;
|
|
137
139
|
export const node = api.node;
|
|
138
140
|
export const pipe = api.pipe;
|
|
141
|
+
export const graph = api.graph;
|
|
139
142
|
export const run = api.run;
|
|
140
143
|
export const rdfsPlusClosure = api.rdfsPlusClosure;
|
|
141
144
|
export const rhoDfClosure = api.rhoDfClosure;
|
|
@@ -177,12 +180,21 @@ export const vcSha256Hex = api.vcSha256Hex;
|
|
|
177
180
|
export const vcEd25519SecretToPublic = api.vcEd25519SecretToPublic;
|
|
178
181
|
export const vcEd25519Sign = api.vcEd25519Sign;
|
|
179
182
|
export const vcEd25519Verify = api.vcEd25519Verify;
|
|
183
|
+
|
|
184
|
+
// XML Encryption 1.1 and JWE; AES through WebCrypto (lib/cipher-host.mjs)
|
|
185
|
+
export const xmlDecrypt = api.xmlDecrypt;
|
|
186
|
+
export const xmlEncrypt = api.xmlEncrypt;
|
|
187
|
+
export const jweDecrypt = api.jweDecrypt;
|
|
188
|
+
export const jweEncrypt = api.jweEncrypt;
|
|
180
189
|
export const vcEddsaCreateFromCanonical = api.vcEddsaCreateFromCanonical;
|
|
181
190
|
export const vcEddsaVerifyFromCanonical = api.vcEddsaVerifyFromCanonical;
|
|
182
191
|
export const vcCheckCredential = api.vcCheckCredential;
|
|
183
192
|
export const vcCheckCredentialSubject = api.vcCheckCredentialSubject;
|
|
184
193
|
export const vcCheckNoDataLoss = api.vcCheckNoDataLoss;
|
|
185
194
|
export const vcCheckRelatedResourceDigests = api.vcCheckRelatedResourceDigests;
|
|
195
|
+
// Controlled Identifiers v1.0 (https://github.com/danbri/factoidal/issues/1100).
|
|
196
|
+
export const cidValidate = api.cidValidate;
|
|
197
|
+
export const cidRetrieveVerificationMethod = api.cidRetrieveVerificationMethod;
|
|
186
198
|
export const didKeyResolve = api.didKeyResolve;
|
|
187
199
|
|
|
188
200
|
// Types, probes and metadata
|
package/index.d.ts
CHANGED
|
@@ -530,6 +530,18 @@ export function closure(
|
|
|
530
530
|
options?: { format?: DataFormat; baseIRI?: string }
|
|
531
531
|
): Promise<Dataset>;
|
|
532
532
|
|
|
533
|
+
/**
|
|
534
|
+
* SPARQL 1.2 RL infer (https://w3c.github.io/data-shapes/sparql12-rl/): the
|
|
535
|
+
* inference graph of the rule set `rules` (SPARQL-RL text) over the default
|
|
536
|
+
* graph of `data`, as a new Dataset. Rejects when the rule set has a syntax
|
|
537
|
+
* error, is not well-formed or not stratifiable, or has IMPORTS.
|
|
538
|
+
*/
|
|
539
|
+
export function sparqlRlInfer(
|
|
540
|
+
data: DataInput,
|
|
541
|
+
rules: string,
|
|
542
|
+
options?: { format?: DataFormat; baseIRI?: string }
|
|
543
|
+
): Promise<Dataset>;
|
|
544
|
+
|
|
533
545
|
/** The syntaxes the engine reads and writes, from the engine (op datasetFormats). */
|
|
534
546
|
export function formats(): Promise<FormatCapability[]>;
|
|
535
547
|
|
|
@@ -574,9 +586,16 @@ export function graphs(dataset: Dataset): Array<[name: NamedNode | BlankNode, gr
|
|
|
574
586
|
* differ only in their graph names got the same hash. To hash a graph
|
|
575
587
|
* whatever its name (for example one entry of graphs()), use
|
|
576
588
|
* canonicalHash(asDefaultGraph(g)). Rejects when the input holds an RDF 1.2
|
|
577
|
-
* triple term or the section 4.4 call budget is exceeded.
|
|
578
|
-
|
|
579
|
-
|
|
589
|
+
* triple term or the section 4.4 call budget is exceeded. The input is what
|
|
590
|
+
* canonicalize() takes: a Dataset, or text with `format` and `baseIRI`.
|
|
591
|
+
* Text is a JavaScript string (characters, not bytes): decode bytes first;
|
|
592
|
+
* the RDF text syntaxes are UTF-8 (`new TextDecoder('utf-8', { fatal: true })`).
|
|
593
|
+
* A Uint8Array is refused.
|
|
594
|
+
*/
|
|
595
|
+
export function canonicalHash(
|
|
596
|
+
data: Dataset | string | { text: string; format?: DataFormat; baseIRI?: string },
|
|
597
|
+
options?: { format?: DataFormat; baseIRI?: string },
|
|
598
|
+
): Promise<string>;
|
|
580
599
|
|
|
581
600
|
/**
|
|
582
601
|
* A new Dataset with the triples of every graph of `dataset`, all in the
|
|
@@ -593,6 +612,15 @@ export function asDefaultGraph(dataset: Dataset): Dataset;
|
|
|
593
612
|
*/
|
|
594
613
|
export function isomorphic(a: DataInput, b: DataInput, options?: { format?: string; baseIRI?: string }): Promise<boolean>;
|
|
595
614
|
|
|
615
|
+
/**
|
|
616
|
+
* The RDF merge of two datasets (RDF 1.1 Semantics 5.2): the quads of both,
|
|
617
|
+
* with the blank nodes of each input kept apart (`_:b` in `a` and `_:b` in
|
|
618
|
+
* `b` are two blank nodes). The engine computes it (op datasetMerge, Lean
|
|
619
|
+
* theorem mergeDatasets_isMerge). Prefixes: those of `a`, then those of `b`
|
|
620
|
+
* whose label `a` does not declare. Since 0.21.0.
|
|
621
|
+
*/
|
|
622
|
+
export function datasetMerge(a: DataInput, b: DataInput, options?: { format?: string; baseIRI?: string }): Promise<Dataset>;
|
|
623
|
+
|
|
596
624
|
/** A Dataset holding RDF/JS quads; each term is sent to the engine as its components. */
|
|
597
625
|
export function fromQuads(quads: Iterable<Quad>): Promise<Dataset>;
|
|
598
626
|
|
|
@@ -937,17 +965,30 @@ export interface Wire<G = unknown> {
|
|
|
937
965
|
evidence: EvidenceRecord[];
|
|
938
966
|
}
|
|
939
967
|
|
|
968
|
+
/** An input port of a node: its name and its wire. */
|
|
969
|
+
export interface NodePort {
|
|
970
|
+
readonly name: string;
|
|
971
|
+
readonly wire: string;
|
|
972
|
+
}
|
|
973
|
+
|
|
940
974
|
/** A node: a registered stage with its parameters. */
|
|
941
975
|
export interface FactoidalNode {
|
|
942
976
|
readonly stage: string;
|
|
943
977
|
readonly kind: string | null;
|
|
944
978
|
/** The engine's status of this node with its settings (see NodeStatus). */
|
|
945
979
|
readonly status: NodeStatus;
|
|
946
|
-
/** The registry status of the stage. */
|
|
947
|
-
readonly registryStatus: StageInfo['status'];
|
|
980
|
+
/** The registry status of the stage; null for a stage with more than one port (not a registry entry). */
|
|
981
|
+
readonly registryStatus: StageInfo['status'] | null;
|
|
948
982
|
readonly contract: string | null;
|
|
949
983
|
readonly assumptions: readonly string[];
|
|
950
|
-
|
|
984
|
+
/**
|
|
985
|
+
* The input ports: one port 'in' for a registry stage; for a stage with
|
|
986
|
+
* more than one port (datasetMerge: 'left', 'right'), the engine's list
|
|
987
|
+
* (op graphCheckNodes). Such a node runs only in graph().
|
|
988
|
+
*/
|
|
989
|
+
readonly ports: readonly NodePort[];
|
|
990
|
+
/** The input wire of a one-port stage; null for a stage with more than one port. */
|
|
991
|
+
readonly wireIn: string | null;
|
|
951
992
|
/**
|
|
952
993
|
* The output wire with these settings: for shippedEvaluator, 'Table' for
|
|
953
994
|
* SELECT, 'Answer' for ASK, 'Dataset' for CONSTRUCT and DESCRIBE (Lean
|
|
@@ -1047,9 +1088,74 @@ export function stages(): Promise<StageInfo[]>;
|
|
|
1047
1088
|
*/
|
|
1048
1089
|
export function node(name: string, params?: Record<string, unknown>): Promise<FactoidalNode>;
|
|
1049
1090
|
|
|
1050
|
-
/** Compose nodes and pipelines left to right. */
|
|
1091
|
+
/** Compose nodes and pipelines left to right. A node with more than one input port throws a TypeError (use graph()). */
|
|
1051
1092
|
export function pipe(...nodes: Array<FactoidalNode | Pipeline>): Pipeline;
|
|
1052
1093
|
|
|
1094
|
+
/** Where a port's value comes from: graph input `input`, or the output of node `node` (an earlier node). */
|
|
1095
|
+
export type GraphSource = { readonly input: number } | { readonly node: number };
|
|
1096
|
+
|
|
1097
|
+
/** The request of graph(). */
|
|
1098
|
+
export interface GraphSpec {
|
|
1099
|
+
/** The wire of each graph input: a wire label of stages() (e.g. 'String', 'Dataset'). */
|
|
1100
|
+
inputs?: string[];
|
|
1101
|
+
/** The nodes in order; `from` has one source per input port of the node. */
|
|
1102
|
+
nodes: Array<{ node: FactoidalNode; from: GraphSource[] }>;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/** An issue of the engine's static check of a graph (op graphCheckNodes, Lean graphIssues). */
|
|
1106
|
+
export type GraphIssue =
|
|
1107
|
+
| { readonly kind: 'unknownInput'; readonly node: number; readonly port: number; readonly portName: string; readonly input: number }
|
|
1108
|
+
| { readonly kind: 'forwardRef'; readonly node: number; readonly port: number; readonly portName: string; readonly ref: number }
|
|
1109
|
+
| { readonly kind: 'portCount'; readonly node: number; readonly ports: number; readonly sources: number }
|
|
1110
|
+
| { readonly kind: 'wireMismatch'; readonly node: number; readonly port: number; readonly portName: string; readonly source: string; readonly portWire: string };
|
|
1111
|
+
|
|
1112
|
+
/** The engine's check of a graph with no issue (op graphCheckNodes). */
|
|
1113
|
+
export interface GraphCheck {
|
|
1114
|
+
readonly issues: readonly GraphIssue[];
|
|
1115
|
+
/** The output wire of the last node. */
|
|
1116
|
+
readonly wireOut: string | null;
|
|
1117
|
+
/** The union of the nodes' named assumptions: the premises of Graph.guarantee_sound. */
|
|
1118
|
+
readonly assumptions: readonly string[];
|
|
1119
|
+
readonly contract: { readonly theorem: string; readonly staticCheck: string };
|
|
1120
|
+
readonly nodes: readonly {
|
|
1121
|
+
readonly name: string; readonly kind: string | null; readonly status: NodeStatus;
|
|
1122
|
+
/** null for a stage with more than one port (not a registry entry). */
|
|
1123
|
+
readonly registryStatus: StageInfo['status'] | null;
|
|
1124
|
+
readonly checked: boolean; readonly contract: string | null;
|
|
1125
|
+
readonly theorems: readonly string[]; readonly assumptions: readonly string[];
|
|
1126
|
+
readonly ports: readonly NodePort[]; readonly wireOut: string;
|
|
1127
|
+
readonly settings: Record<string, unknown>; readonly settingsDigest: string;
|
|
1128
|
+
readonly roles: Readonly<Record<string, string>>;
|
|
1129
|
+
readonly outside: readonly OutsideSetting[];
|
|
1130
|
+
readonly derived: Readonly<Record<string, string>>;
|
|
1131
|
+
}[];
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
/** A graph from graph(): checked by the engine, with no issue. */
|
|
1135
|
+
export interface FactoidalGraph {
|
|
1136
|
+
readonly inputs: readonly string[];
|
|
1137
|
+
readonly nodes: readonly { readonly node: FactoidalNode; readonly from: readonly GraphSource[] }[];
|
|
1138
|
+
readonly wireOut: string | null;
|
|
1139
|
+
readonly assumptions: readonly string[];
|
|
1140
|
+
readonly check: GraphCheck;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
/** The result of run() on a graph. */
|
|
1144
|
+
export interface GraphRunResult<G = unknown> extends RunResult<G> {
|
|
1145
|
+
/** The output of each node, in order; `graph` is the last one. */
|
|
1146
|
+
values: unknown[];
|
|
1147
|
+
issues: GraphIssue[];
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* A pipeline that is an acyclic graph of nodes with named input ports
|
|
1152
|
+
* (https://github.com/danbri/factoidal/issues/1130). The engine's op
|
|
1153
|
+
* graphCheckNodes checks it: a graph with an issue throws a FactoidalError
|
|
1154
|
+
* (code 'op.failed') whose `issues` is the engine's list; an engine without
|
|
1155
|
+
* the op throws code 'op.unknown'. Since 0.21.0.
|
|
1156
|
+
*/
|
|
1157
|
+
export function graph(spec: GraphSpec): FactoidalGraph;
|
|
1158
|
+
|
|
1053
1159
|
/**
|
|
1054
1160
|
* Run a node or pipeline on `input` (a Wire, or the graph: text for a
|
|
1055
1161
|
* reader, else a Dataset or data input). Rejects before any node runs when
|
|
@@ -1061,6 +1167,12 @@ export function pipe(...nodes: Array<FactoidalNode | Pipeline>): Pipeline;
|
|
|
1061
1167
|
* `wireOut` (see Wire).
|
|
1062
1168
|
*/
|
|
1063
1169
|
export function run(pipeline: FactoidalNode | Pipeline, input: unknown, options?: RunOptions): Promise<RunResult>;
|
|
1170
|
+
/**
|
|
1171
|
+
* Run a graph on `inputs`, one value per graph input. Each node runs on the
|
|
1172
|
+
* values of its sources (a node with more than one port gets them in port
|
|
1173
|
+
* order); one evidence record per node, with `node` (its index) and `from`.
|
|
1174
|
+
*/
|
|
1175
|
+
export function run(graph: FactoidalGraph, inputs: unknown[], options?: RunOptions): Promise<GraphRunResult>;
|
|
1064
1176
|
|
|
1065
1177
|
/** Literature-name alias for coreRdfsClosure (ρdf). */
|
|
1066
1178
|
export function rhoDfClosure(
|
|
@@ -1374,6 +1486,10 @@ export interface Sbm11Store {
|
|
|
1374
1486
|
terms: number;
|
|
1375
1487
|
/** how the engine checks reads; undefined from a wasm module built before the Merkle check */
|
|
1376
1488
|
verify: 'merkle' | 'none' | undefined;
|
|
1489
|
+
/** the SHA-256 of the bytes of manifest.sbm11, 64 lowercase hex digits, as
|
|
1490
|
+
* the engine computed it at open (pin it, then give it as
|
|
1491
|
+
* `manifestSha256`); undefined from a wasm module built before issue 1105 */
|
|
1492
|
+
manifestSha256: string | undefined;
|
|
1377
1493
|
query(sparql: string, options?: { base?: string; sparql12?: boolean; reference?: boolean }): Sbm11Answer;
|
|
1378
1494
|
/** the resources the reader read, when its reader records them (lwsSbm11Reader) */
|
|
1379
1495
|
readonly evidence: Sbm11ReadEvidence[] | undefined;
|
|
@@ -1384,8 +1500,13 @@ export interface Sbm11Store {
|
|
|
1384
1500
|
* Node: `source` is a directory unless a reader is given or registered.
|
|
1385
1501
|
* `verify` (default 'merkle'): the engine checks every byte it decodes against
|
|
1386
1502
|
* the manifest's Merkle roots and refuses a changed file with its name;
|
|
1387
|
-
* 'none' checks lengths only.
|
|
1388
|
-
|
|
1503
|
+
* 'none' checks lengths only.
|
|
1504
|
+
* `manifestSha256`: the trust anchor, the SHA-256 of the bytes of
|
|
1505
|
+
* manifest.sbm11 as 64 hex digits (https://github.com/danbri/factoidal/issues/1105);
|
|
1506
|
+
* the engine refuses the open when the manifest has another digest. */
|
|
1507
|
+
export function openSbm11(source: string, options?: {
|
|
1508
|
+
reader?: Sbm11Reader; verify?: 'merkle' | 'none'; manifestSha256?: string
|
|
1509
|
+
}): Promise<Sbm11Store>;
|
|
1389
1510
|
|
|
1390
1511
|
/** Serve `source` with `reader`; `null` removes it. */
|
|
1391
1512
|
export function registerSbm11Source(source: string, reader: Sbm11Reader | null): void;
|
|
@@ -1749,6 +1870,45 @@ export function vcEd25519Verify(
|
|
|
1749
1870
|
signatureHex: string
|
|
1750
1871
|
): Promise<boolean>;
|
|
1751
1872
|
|
|
1873
|
+
/**
|
|
1874
|
+
* Decrypt every xenc:EncryptedData of an XML document (XML Encryption 1.1).
|
|
1875
|
+
* RSA-OAEP, ECDH-ES and X25519 run in the wasm (HACL*); AES runs in the
|
|
1876
|
+
* host's WebCrypto. Every failure after the structure check is the one
|
|
1877
|
+
* error "XML decryption failed".
|
|
1878
|
+
*/
|
|
1879
|
+
export function xmlDecrypt(
|
|
1880
|
+
document: string,
|
|
1881
|
+
options: { keys: object[]; allowCbc?: boolean }
|
|
1882
|
+
): Promise<{ document: string; canonical: string }>;
|
|
1883
|
+
|
|
1884
|
+
/** Encrypt an XML document element, or its content, for one recipient. */
|
|
1885
|
+
export function xmlEncrypt(
|
|
1886
|
+
document: string,
|
|
1887
|
+
options: {
|
|
1888
|
+
recipient: object;
|
|
1889
|
+
algorithm?: 'aes128-gcm' | 'aes256-gcm';
|
|
1890
|
+
keyTransport?: 'rsa-oaep-mgf1p' | 'rsa-oaep-sha256';
|
|
1891
|
+
keyWrap?: 'kw-aes128' | 'kw-aes256';
|
|
1892
|
+
content?: boolean;
|
|
1893
|
+
saml?: boolean;
|
|
1894
|
+
}
|
|
1895
|
+
): Promise<{ document: string; canonical: string }>;
|
|
1896
|
+
|
|
1897
|
+
/**
|
|
1898
|
+
* Decrypt a compact JWE (RFC 7516). Every failure after the allowlist is
|
|
1899
|
+
* the one error "decryption failed".
|
|
1900
|
+
*/
|
|
1901
|
+
export function jweDecrypt(
|
|
1902
|
+
token: string,
|
|
1903
|
+
options: { jwk: object }
|
|
1904
|
+
): Promise<{ header: Record<string, unknown>; plaintext: Uint8Array }>;
|
|
1905
|
+
|
|
1906
|
+
/** Encrypt to a compact JWE (RFC 7516). */
|
|
1907
|
+
export function jweEncrypt(
|
|
1908
|
+
plaintext: Uint8Array | string,
|
|
1909
|
+
options: { alg: string; enc: string; jwk: object; header?: Record<string, unknown> }
|
|
1910
|
+
): Promise<string>;
|
|
1911
|
+
|
|
1752
1912
|
/**
|
|
1753
1913
|
* Create an eddsa-rdfc-2022 Data Integrity proofValue (multibase-z,
|
|
1754
1914
|
* base58btc) over already-canonicalized inputs — RDFC-1.0 canonical
|
|
@@ -1817,6 +1977,70 @@ export function vcCheckRelatedResourceDigests(
|
|
|
1817
1977
|
credentialJson: string
|
|
1818
1978
|
): Promise<{ valid: boolean; reason?: string }>;
|
|
1819
1979
|
|
|
1980
|
+
/** One failed MUST of CID 1.0 §2 (cidValidate). */
|
|
1981
|
+
export interface CidValidationError {
|
|
1982
|
+
/** The engine's name of the failed MUST, e.g. 'idNotUrl', 'jwkPrivateMember'. */
|
|
1983
|
+
code: string;
|
|
1984
|
+
message: string;
|
|
1985
|
+
/** RFC 6901 JSON Pointer to the member, e.g. '/verificationMethod/1/publicKeyJwk/d'; '' is the whole document. */
|
|
1986
|
+
path: string;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
/**
|
|
1990
|
+
* Controlled Identifiers v1.0 §2 (https://www.w3.org/TR/cid-1.0/): check a
|
|
1991
|
+
* controlled identifier document. `valid` is the engine's answer
|
|
1992
|
+
* (L4Factoidal.CID.parseDocument); `errors` lists every failed MUST it found,
|
|
1993
|
+
* empty when valid. Issue 1100 item 9.
|
|
1994
|
+
*/
|
|
1995
|
+
export function cidValidate(doc: string | object): Promise<{ valid: boolean; errors: CidValidationError[] }>;
|
|
1996
|
+
|
|
1997
|
+
/** An RFC 9457 problem details object. */
|
|
1998
|
+
export interface CidProblem {
|
|
1999
|
+
/** https://w3id.org/security#<NAME> for a §3.5 error; a tag: URI for the others. */
|
|
2000
|
+
type: string;
|
|
2001
|
+
title: string;
|
|
2002
|
+
detail: string;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
2005
|
+
export interface CidRetrieveOptions {
|
|
2006
|
+
/**
|
|
2007
|
+
* GET the URL the engine names. Called as fetch(url, init) with
|
|
2008
|
+
* init.headers.accept, init.redirect 'manual' and, when the engine chose
|
|
2009
|
+
* one, init.address (the address to connect to). Answers a Response, or
|
|
2010
|
+
* { status, headers: { get(name) }, text() }. Default: Node and Deno
|
|
2011
|
+
* connect to init.address; a browser uses the page's fetch.
|
|
2012
|
+
*/
|
|
2013
|
+
fetch?: (url: string, init: { method: 'GET'; headers: { accept: string }; redirect: 'manual'; address?: string }) =>
|
|
2014
|
+
Promise<{ status: number; headers: { get(name: string): string | null }; text(): Promise<string> }>;
|
|
2015
|
+
/** Every address of a host name. Default: the system resolver (Node, Deno); none in a browser. null: none. */
|
|
2016
|
+
resolve?: ((host: string) => Promise<string[]>) | null;
|
|
2017
|
+
/** Refuse a method that has expired or been revoked at this time (a Date, or seconds since the epoch). */
|
|
2018
|
+
now?: Date | number;
|
|
2019
|
+
/** Allow an http document URL (default: https only). */
|
|
2020
|
+
allowHttp?: boolean;
|
|
2021
|
+
/** Allow loopback, link-local, private and localhost addresses (default: refused). */
|
|
2022
|
+
allowPrivateFetch?: boolean;
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
/**
|
|
2026
|
+
* Controlled Identifiers v1.0 §3.3 Retrieve Verification Method. The engine
|
|
2027
|
+
* names each fetch and decides each answer (the private-address guard of the
|
|
2028
|
+
* authorization server, the status, the Content-Type: application/cid,
|
|
2029
|
+
* application/cid+json, application/ld+json or application/json, then §3.3);
|
|
2030
|
+
* this function does the fetch. Never rejects for a failed retrieval: it
|
|
2031
|
+
* answers `ok: false` with the §3.5 name (or FETCH_REFUSED, FETCH_FAILED,
|
|
2032
|
+
* UNSUPPORTED_MEDIA_TYPE, VERIFICATION_METHOD_NOT_IN_FORCE) and an RFC 9457
|
|
2033
|
+
* object. Issue 1100 items 7 and 9.
|
|
2034
|
+
*/
|
|
2035
|
+
export function cidRetrieveVerificationMethod(
|
|
2036
|
+
url: string,
|
|
2037
|
+
relationship: 'authentication' | 'assertionMethod' | 'keyAgreement' | 'capabilityInvocation' | 'capabilityDelegation',
|
|
2038
|
+
options?: CidRetrieveOptions
|
|
2039
|
+
): Promise<
|
|
2040
|
+
| { ok: true; verificationMethod: Record<string, unknown>; controllerDocument: string }
|
|
2041
|
+
| { ok: false; code: string; problem: CidProblem }
|
|
2042
|
+
>;
|
|
2043
|
+
|
|
1820
2044
|
/**
|
|
1821
2045
|
* Feature probe: which ops the loaded wasm module serves. A module older
|
|
1822
2046
|
* than this package can lack some; an operation whose op is missing
|
|
@@ -1831,6 +2055,8 @@ export function capabilities(): Promise<{
|
|
|
1831
2055
|
canonicalHash: boolean;
|
|
1832
2056
|
shacl: boolean;
|
|
1833
2057
|
shex: boolean;
|
|
2058
|
+
/** the engine has the SPARQL 1.2 RL op (datasetSparqlRlInfer) */
|
|
2059
|
+
sparqlRl: boolean;
|
|
1834
2060
|
owlClosure: boolean;
|
|
1835
2061
|
explain: boolean;
|
|
1836
2062
|
stages: boolean;
|
|
@@ -1838,6 +2064,10 @@ export function capabilities(): Promise<{
|
|
|
1838
2064
|
pipelineCheck: boolean;
|
|
1839
2065
|
/** The op pipelineCheckNodes: node settings in evidence, and the evaluator's output wire from the query form. */
|
|
1840
2066
|
pipelineCheckNodes: boolean;
|
|
2067
|
+
/** The op graphCheckNodes: graph() and run() of a graph, and node('datasetMerge'). */
|
|
2068
|
+
graphCheck: boolean;
|
|
2069
|
+
/** The op datasetMerge: datasetMerge(). */
|
|
2070
|
+
datasetMerge: boolean;
|
|
1841
2071
|
tableau: boolean;
|
|
1842
2072
|
rml: boolean;
|
|
1843
2073
|
csvw: boolean;
|
|
@@ -1867,6 +2097,8 @@ export function capabilities(): Promise<{
|
|
|
1867
2097
|
deltaLog: boolean;
|
|
1868
2098
|
/** ops literalValue and literalFromValue (issue 1051). */
|
|
1869
2099
|
literalValues: boolean;
|
|
2100
|
+
/** ops cidValidate and cidRetrieve (issue 1100). */
|
|
2101
|
+
cid: boolean;
|
|
1870
2102
|
/** 'full': the whole library is in the wasm module. */
|
|
1871
2103
|
profile: 'full' | string;
|
|
1872
2104
|
/** The dispatch ABI version string of the loaded wasm module. */
|
|
@@ -1945,6 +2177,7 @@ declare const _default: {
|
|
|
1945
2177
|
update: typeof update;
|
|
1946
2178
|
openDataset: typeof openDataset;
|
|
1947
2179
|
closure: typeof closure;
|
|
2180
|
+
sparqlRlInfer: typeof sparqlRlInfer;
|
|
1948
2181
|
formats: typeof formats;
|
|
1949
2182
|
serialize: typeof serialize;
|
|
1950
2183
|
canonicalize: typeof canonicalize;
|
|
@@ -2005,12 +2238,18 @@ declare const _default: {
|
|
|
2005
2238
|
vcEd25519SecretToPublic: typeof vcEd25519SecretToPublic;
|
|
2006
2239
|
vcEd25519Sign: typeof vcEd25519Sign;
|
|
2007
2240
|
vcEd25519Verify: typeof vcEd25519Verify;
|
|
2241
|
+
xmlDecrypt: typeof xmlDecrypt;
|
|
2242
|
+
xmlEncrypt: typeof xmlEncrypt;
|
|
2243
|
+
jweDecrypt: typeof jweDecrypt;
|
|
2244
|
+
jweEncrypt: typeof jweEncrypt;
|
|
2008
2245
|
vcEddsaCreateFromCanonical: typeof vcEddsaCreateFromCanonical;
|
|
2009
2246
|
vcEddsaVerifyFromCanonical: typeof vcEddsaVerifyFromCanonical;
|
|
2010
2247
|
vcCheckCredential: typeof vcCheckCredential;
|
|
2011
2248
|
vcCheckCredentialSubject: typeof vcCheckCredentialSubject;
|
|
2012
2249
|
vcCheckNoDataLoss: typeof vcCheckNoDataLoss;
|
|
2013
2250
|
vcCheckRelatedResourceDigests: typeof vcCheckRelatedResourceDigests;
|
|
2251
|
+
cidValidate: typeof cidValidate;
|
|
2252
|
+
cidRetrieveVerificationMethod: typeof cidRetrieveVerificationMethod;
|
|
2014
2253
|
capabilities: typeof capabilities;
|
|
2015
2254
|
Dataset: typeof Dataset;
|
|
2016
2255
|
Store: typeof Store;
|
package/index.mjs
CHANGED
|
@@ -25,6 +25,7 @@ import { sbm11Api, registerSbm11Source, setDefaultSbm11Reader, mapReader } from
|
|
|
25
25
|
import { nodeDefaultReaderFactory } from './lib/sbm11-node.mjs';
|
|
26
26
|
import { lwsSbm11Reader as lwsSbm11ReaderWith } from './lib/sbm11-lws.mjs';
|
|
27
27
|
import { nodeSyncTransport } from './lib/sync-http-node.mjs';
|
|
28
|
+
import { nodeCidHost } from './lib/cid-node.mjs';
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* The loaded Lean engine handle: `call(op, args)`, `callBlob`,
|
|
@@ -45,6 +46,8 @@ const api = buildApi({
|
|
|
45
46
|
engineName: 'lean4-wasm',
|
|
46
47
|
loadEntry: async () => entryFromEngine(await loadEngine()),
|
|
47
48
|
storeReaderFor: (root) => (path) => readFileSync(join(root, path)),
|
|
49
|
+
// Name resolution and a GET pinned to one address (issue 1100 item 9).
|
|
50
|
+
cidHost: nodeCidHost,
|
|
48
51
|
});
|
|
49
52
|
|
|
50
53
|
// RDF and SPARQL
|
|
@@ -57,6 +60,7 @@ export const graphs = api.graphs;
|
|
|
57
60
|
export const canonicalHash = api.canonicalHash;
|
|
58
61
|
export const asDefaultGraph = api.asDefaultGraph;
|
|
59
62
|
export const isomorphic = api.isomorphic;
|
|
63
|
+
export const datasetMerge = api.datasetMerge;
|
|
60
64
|
export const fromQuads = api.fromQuads;
|
|
61
65
|
// Literal values (https://github.com/danbri/factoidal/issues/1051): synchronous
|
|
62
66
|
// after the engine is loaded.
|
|
@@ -75,6 +79,7 @@ export const memberIri = api.memberIri;
|
|
|
75
79
|
export const memberOrdinal = api.memberOrdinal;
|
|
76
80
|
export const openDataset = api.openDataset;
|
|
77
81
|
export const closure = api.closure;
|
|
82
|
+
export const sparqlRlInfer = api.sparqlRlInfer;
|
|
78
83
|
export const formats = api.formats;
|
|
79
84
|
export const queryRaw = api.queryRaw;
|
|
80
85
|
export const queryHdt = api.queryHdt;
|
|
@@ -129,6 +134,7 @@ export const explain = api.explain;
|
|
|
129
134
|
export const stages = api.stages;
|
|
130
135
|
export const node = api.node;
|
|
131
136
|
export const pipe = api.pipe;
|
|
137
|
+
export const graph = api.graph;
|
|
132
138
|
export const run = api.run;
|
|
133
139
|
export const rdfsPlusClosure = api.rdfsPlusClosure;
|
|
134
140
|
export const rhoDfClosure = api.rhoDfClosure;
|
|
@@ -170,12 +176,21 @@ export const vcSha256Hex = api.vcSha256Hex;
|
|
|
170
176
|
export const vcEd25519SecretToPublic = api.vcEd25519SecretToPublic;
|
|
171
177
|
export const vcEd25519Sign = api.vcEd25519Sign;
|
|
172
178
|
export const vcEd25519Verify = api.vcEd25519Verify;
|
|
179
|
+
|
|
180
|
+
// XML Encryption 1.1 and JWE; AES through WebCrypto (lib/cipher-host.mjs)
|
|
181
|
+
export const xmlDecrypt = api.xmlDecrypt;
|
|
182
|
+
export const xmlEncrypt = api.xmlEncrypt;
|
|
183
|
+
export const jweDecrypt = api.jweDecrypt;
|
|
184
|
+
export const jweEncrypt = api.jweEncrypt;
|
|
173
185
|
export const vcEddsaCreateFromCanonical = api.vcEddsaCreateFromCanonical;
|
|
174
186
|
export const vcEddsaVerifyFromCanonical = api.vcEddsaVerifyFromCanonical;
|
|
175
187
|
export const vcCheckCredential = api.vcCheckCredential;
|
|
176
188
|
export const vcCheckCredentialSubject = api.vcCheckCredentialSubject;
|
|
177
189
|
export const vcCheckNoDataLoss = api.vcCheckNoDataLoss;
|
|
178
190
|
export const vcCheckRelatedResourceDigests = api.vcCheckRelatedResourceDigests;
|
|
191
|
+
// Controlled Identifiers v1.0 (https://github.com/danbri/factoidal/issues/1100).
|
|
192
|
+
export const cidValidate = api.cidValidate;
|
|
193
|
+
export const cidRetrieveVerificationMethod = api.cidRetrieveVerificationMethod;
|
|
179
194
|
export const didKeyResolve = api.didKeyResolve;
|
|
180
195
|
|
|
181
196
|
// Types, probes and metadata
|
package/l4-assets/l4factoidal.js
CHANGED
|
Binary file
|
package/l4-assets/version.json
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
"engine": "lean4",
|
|
3
3
|
"note": "The Lean 4 (L4Factoidal) engine build provenance and claims: the only engine of @factoidal/core since 0.9.0 (issue 713). This committed file is a placeholder. tools/fetch-builds.sh --set web (through tools/stamp-l4-version.mjs) writes the provenance members from the danbri/factoidal-builds release that built the wasm; formal/lean4/Wasm/build-wasm.sh step 9 writes them for a local build. Do not commit a stamped copy.",
|
|
4
4
|
"stamped": true,
|
|
5
|
-
"release": "danbri/factoidal-builds build-
|
|
6
|
-
"releaseRun": "https://github.com/danbri/factoidal-builds/actions/runs/
|
|
7
|
-
"gitSha": "
|
|
8
|
-
"builtAt": "2026-10-
|
|
5
|
+
"release": "danbri/factoidal-builds build-7ab6936b6710-web",
|
|
6
|
+
"releaseRun": "https://github.com/danbri/factoidal-builds/actions/runs/40733510537",
|
|
7
|
+
"gitSha": "7ab6936b6710f2a68517a1fd3a1bf047e96c3c7c",
|
|
8
|
+
"builtAt": "2026-10-28T17:53:09Z",
|
|
9
9
|
"leanToolchain": "leanprover/lean4:v4.33.1",
|
|
10
10
|
"emscripten": "6.0.8",
|
|
11
11
|
"abiVersion": "1",
|
|
12
12
|
"engineVersion": "l4factoidal-wasm 0.2.0 (dispatch: RDF parse/serialize, SPARQL query+update, RDFS/OWL-RL closures, RDFC-1.0, CL/IKL)",
|
|
13
13
|
"version": "l4factoidal-wasm 0.2.0 (dispatch: RDF parse/serialize, SPARQL query+update, RDFS/OWL-RL closures, RDFC-1.0, CL/IKL)",
|
|
14
|
-
"wasmSha256": "
|
|
15
|
-
"wasmBytes":
|
|
14
|
+
"wasmSha256": "18074526651eb00293b15be5c6d6e117e9d07271f1d104340b9d9ecff3b826c2",
|
|
15
|
+
"wasmBytes": 19211990,
|
|
16
16
|
"claims": {
|
|
17
17
|
"source": "formal/lean4 (L4Factoidal): no sorry, no user axioms, no native_decide; W3C behaviour pinned by build-time #guard",
|
|
18
18
|
"suitesAtBuildSha": "see docs/test-results and formal/lean4/PORT_NOTES.md at gitSha"
|