@trylimbo/sdk-verifier-wasm 0.2.25 → 0.3.0-canary.40
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/gen/wasm/comlink.js +1 -1
- package/gen/wasm/trylimbo_sdk_verifier.d.ts +306 -331
- package/gen/wasm/trylimbo_sdk_verifier.js +258 -301
- package/gen/wasm/trylimbo_sdk_verifier_bg.wasm +0 -0
- package/gen/wasm/trylimbo_sdk_verifier_bg.wasm.d.ts +21 -27
- package/gen/wasm/worker-thread.js +246 -313
- package/gen/wasm/worker.d.ts +321 -312
- package/gen/wasm/worker.js +1 -1
- package/package.json +1 -1
package/gen/wasm/worker.d.ts
CHANGED
|
@@ -163,141 +163,61 @@ interface RangeSource {
|
|
|
163
163
|
readAt: (offset: number, length: number) => Uint8Array;
|
|
164
164
|
}
|
|
165
165
|
/**
|
|
166
|
-
* A
|
|
167
|
-
* list, e.g. `io.iscc.v0`) plus its algorithm-specific value (the `ISCC:…` code,
|
|
168
|
-
* a watermark token, …). The signer embeds it as a `c2pa.soft-binding` assertion
|
|
169
|
-
* and indexes it, so a transcoded copy whose exact content hash no longer
|
|
170
|
-
* matches still recovers the manifest from the repository.
|
|
166
|
+
* A `soft-binding-block-map`. No scope is the whole content.
|
|
171
167
|
*/
|
|
172
|
-
interface
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
*/
|
|
176
|
-
alg: string;
|
|
177
|
-
/**
|
|
178
|
-
* Algorithm-specific binding value: the canonical string the algorithm
|
|
179
|
-
* produces (an `ISCC:…` code, a watermark token). Its UTF-8 bytes are what
|
|
180
|
-
* the repository lookup base64-encodes.
|
|
181
|
-
*/
|
|
182
|
-
value: string;
|
|
168
|
+
interface Block {
|
|
169
|
+
value: Uint8Array;
|
|
170
|
+
scope?: Scope;
|
|
183
171
|
}
|
|
184
172
|
/**
|
|
185
|
-
* A
|
|
186
|
-
* SDK\'s own two. A browser has no host binder: a detector runs repository-side.
|
|
173
|
+
* A `soft-binding-scope-map`.
|
|
187
174
|
*/
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
} | {
|
|
191
|
-
kind: "held";
|
|
192
|
-
binding: SoftBinding;
|
|
193
|
-
};
|
|
194
|
-
/**
|
|
195
|
-
* A session signing key from the init manifest\'s roster (spec §19.4.4).
|
|
196
|
-
*/
|
|
197
|
-
interface SessionKeySummary {
|
|
198
|
-
/**
|
|
199
|
-
* Identifier of the session signing key.
|
|
200
|
-
*/
|
|
201
|
-
keyId: Uint8Array;
|
|
202
|
-
/**
|
|
203
|
-
* The session key\'s public half (SEC1-encoded bytes).
|
|
204
|
-
*/
|
|
205
|
-
publicKey: Uint8Array;
|
|
175
|
+
interface Scope {
|
|
176
|
+
timespan?: Timespan;
|
|
206
177
|
}
|
|
207
178
|
/**
|
|
208
|
-
*
|
|
179
|
+
* A `soft-binding-timespan-map`: where the range starts in the media and how long it lasts, in
|
|
180
|
+
* milliseconds.
|
|
209
181
|
*/
|
|
210
|
-
|
|
182
|
+
interface Timespan {
|
|
183
|
+
start: number;
|
|
184
|
+
duration: number;
|
|
185
|
+
}
|
|
211
186
|
/**
|
|
212
|
-
*
|
|
213
|
-
* binding). Every field is stated: nothing here is chosen on the caller\'s behalf.
|
|
214
|
-
*
|
|
215
|
-
* One definition, all lanes: `#[binding]` derives the shapes directly here:
|
|
216
|
-
* tsify (camelCase) on wasm, a `uniffi::Record` on the native `ffi` build, so there is no
|
|
217
|
-
* per-lane DTO copy. Off both lanes it is a plain struct.
|
|
187
|
+
* A session signing key from the init manifest\'s roster (spec §19.4.4).
|
|
218
188
|
*/
|
|
219
|
-
interface
|
|
189
|
+
interface SessionKey {
|
|
220
190
|
/**
|
|
221
|
-
*
|
|
222
|
-
* for exactly the algorithms it may be asked for. Results merge by manifest, and a match\'s
|
|
223
|
-
* `endpoint` is fetched from only when it names one of these. Empty: no recovery can be
|
|
224
|
-
* asked of this verifier.
|
|
225
|
-
*/
|
|
226
|
-
repositories: Repository[];
|
|
227
|
-
/**
|
|
228
|
-
* PEM trust anchors for the manifest signers the caller trusts.
|
|
229
|
-
*/
|
|
230
|
-
trustAnchors: string[];
|
|
231
|
-
/**
|
|
232
|
-
* PEM trust anchors for the time-stamping authorities the caller trusts.
|
|
233
|
-
*/
|
|
234
|
-
tsaTrustAnchors: string[];
|
|
235
|
-
/**
|
|
236
|
-
* Also trust the bundled official C2PA anchors, manifest and TSA lists, beside the
|
|
237
|
-
* caller\'s. `false` trusts the caller\'s lists alone.
|
|
191
|
+
* Identifier of the session signing key.
|
|
238
192
|
*/
|
|
239
|
-
|
|
193
|
+
kid: Uint8Array;
|
|
240
194
|
/**
|
|
241
|
-
*
|
|
242
|
-
* exactly against the credential issuer. Empty trusts no issuer: every identity assertion
|
|
243
|
-
* then reports `cawg.ica.untrusted_issuer` and withholds `cawg.ica.credential_valid`,
|
|
244
|
-
* which leaves the manifest\'s own validity untouched.
|
|
195
|
+
* SEC1 EC, raw Ed25519 or PKCS#1 DER RSA public-key bytes.
|
|
245
196
|
*/
|
|
246
|
-
|
|
197
|
+
publicKey: Uint8Array;
|
|
247
198
|
}
|
|
248
199
|
/**
|
|
249
|
-
*
|
|
250
|
-
* JS binding). Every field is stated: nothing here is chosen on the caller\'s behalf.
|
|
251
|
-
*
|
|
252
|
-
* `#[binding]` derives the wasm shape (`trustC2paAnchors` camelCase) and,
|
|
253
|
-
* with `ffi`, a `uniffi::Record` for the native `StreamVerifier.create` binding, so there
|
|
254
|
-
* is no per-lane DTO copy. Off both lanes it is a plain struct.
|
|
200
|
+
* An asset a repository downloads, as the `byReference` request body names it.
|
|
255
201
|
*/
|
|
256
|
-
interface
|
|
257
|
-
/**
|
|
258
|
-
* PEM trust anchors for the manifest signers the caller trusts.
|
|
259
|
-
*/
|
|
260
|
-
trustAnchors: string[];
|
|
202
|
+
interface Reference {
|
|
261
203
|
/**
|
|
262
|
-
*
|
|
204
|
+
* A short-lived https URL without credentials.
|
|
263
205
|
*/
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Also trust the bundled official C2PA anchors, manifest and TSA lists, beside the
|
|
267
|
-
* caller\'s. `false` trusts the caller\'s lists alone.
|
|
268
|
-
*/
|
|
269
|
-
trustC2paAnchors: boolean;
|
|
206
|
+
url: string;
|
|
270
207
|
/**
|
|
271
|
-
*
|
|
272
|
-
* exactly against the credential issuer. Empty trusts no issuer: an identity assertion
|
|
273
|
-
* on the init segment\'s manifest then reports `cawg.ica.untrusted_issuer` and withholds
|
|
274
|
-
* `cawg.ica.credential_valid`.
|
|
208
|
+
* The asset\'s size in bytes.
|
|
275
209
|
*/
|
|
276
|
-
|
|
210
|
+
length: number;
|
|
277
211
|
/**
|
|
278
|
-
*
|
|
279
|
-
* skewed, in seconds: the deployment\'s own encoder-clock allowance, stated rather than
|
|
280
|
-
* assumed.
|
|
212
|
+
* The asset\'s media type.
|
|
281
213
|
*/
|
|
282
|
-
|
|
214
|
+
format?: string;
|
|
215
|
+
ranges?: import('@contentauth/c2pa-types').Range[];
|
|
283
216
|
}
|
|
284
217
|
/**
|
|
285
|
-
*
|
|
286
|
-
* the native lane\'s `DeriveOptions` is, spelled as data.
|
|
287
|
-
*/
|
|
288
|
-
interface DeriveOptions {
|
|
289
|
-
format: AssetFormat;
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* How a call knows the asset\'s format: stated by the caller, or read from the leading bytes.
|
|
293
|
-
* Stated, never defaulted: sniffing is a choice made by name.
|
|
218
|
+
* C2PA validation state of a manifest (spec §14.3).
|
|
294
219
|
*/
|
|
295
|
-
type
|
|
296
|
-
kind: "sniff";
|
|
297
|
-
} | {
|
|
298
|
-
kind: "declared";
|
|
299
|
-
mediaType: string;
|
|
300
|
-
};
|
|
220
|
+
type ValidationState = "Invalid" | "Valid" | "Trusted";
|
|
301
221
|
/**
|
|
302
222
|
* One C2PA manifest repository, as the Soft Binding Resolution API spec lets a client find it.
|
|
303
223
|
*/
|
|
@@ -306,8 +226,8 @@ type Repository = {
|
|
|
306
226
|
url: string;
|
|
307
227
|
algorithms: string[];
|
|
308
228
|
} | {
|
|
309
|
-
kind: "
|
|
310
|
-
|
|
229
|
+
kind: "registered";
|
|
230
|
+
alg: string;
|
|
311
231
|
};
|
|
312
232
|
/**
|
|
313
233
|
* One C2PA validation status entry (spec §15.3): the registered code, its kind, and the
|
|
@@ -331,13 +251,7 @@ interface ValidationCode {
|
|
|
331
251
|
*/
|
|
332
252
|
interface Credential {
|
|
333
253
|
/**
|
|
334
|
-
*
|
|
335
|
-
* `identifier`: each manifest\'s claim thumbnail and each ingredient\'s. The manifests state
|
|
336
|
-
* identifiers and no images, so this is what a chain draws from.
|
|
337
|
-
*/
|
|
338
|
-
thumbnails: Record<string, Uint8Array>;
|
|
339
|
-
/**
|
|
340
|
-
* Where this credential came from. See [`CredentialOrigin`].
|
|
254
|
+
* Where this credential came from.
|
|
341
255
|
*/
|
|
342
256
|
origin: CredentialOrigin;
|
|
343
257
|
manifest: import('@contentauth/c2pa-types').ManifestStore;
|
|
@@ -346,17 +260,38 @@ interface Credential {
|
|
|
346
260
|
*/
|
|
347
261
|
hardBinding: HardBinding;
|
|
348
262
|
/**
|
|
349
|
-
* Where this credential sits among the others returned.
|
|
263
|
+
* Where this credential sits among the others returned.
|
|
350
264
|
*/
|
|
351
265
|
lineage: Lineage;
|
|
352
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* One query that located a recovered credential: how it was asked, under which algorithm, and
|
|
269
|
+
* where the manifest came from.
|
|
270
|
+
*/
|
|
271
|
+
interface Discovery {
|
|
272
|
+
via: DiscoveryVia;
|
|
273
|
+
alg: string;
|
|
274
|
+
type: SoftBindingType;
|
|
275
|
+
/**
|
|
276
|
+
* 0-100, the repository\'s `similarityScore`.
|
|
277
|
+
*/
|
|
278
|
+
score?: number;
|
|
279
|
+
repository: string;
|
|
280
|
+
/**
|
|
281
|
+
* The resolution API the manifest was fetched from, when not `repository`.
|
|
282
|
+
*/
|
|
283
|
+
endpoint?: string;
|
|
284
|
+
}
|
|
353
285
|
/**
|
|
354
286
|
* Outcome of validating a media segment against its stream\'s init.
|
|
355
287
|
*/
|
|
356
288
|
interface MediaValidation {
|
|
357
|
-
|
|
289
|
+
/**
|
|
290
|
+
* `invalid` on any failure, else the state of the init manifest the segment\'s key came from.
|
|
291
|
+
*/
|
|
292
|
+
state: ValidationState;
|
|
358
293
|
codes: ValidationCode[];
|
|
359
|
-
|
|
294
|
+
kid: Uint8Array;
|
|
360
295
|
timing: SegmentTiming;
|
|
361
296
|
manifestId: string;
|
|
362
297
|
}
|
|
@@ -367,7 +302,7 @@ interface InitValidation {
|
|
|
367
302
|
state: ValidationState;
|
|
368
303
|
codes: ValidationCode[];
|
|
369
304
|
manifest: import('@contentauth/c2pa-types').ManifestStore;
|
|
370
|
-
sessionKeys:
|
|
305
|
+
sessionKeys: SessionKey[];
|
|
371
306
|
}
|
|
372
307
|
/**
|
|
373
308
|
* Result of `StreamSession.validate`, discriminated by `kind`.
|
|
@@ -376,84 +311,223 @@ type SegmentValidation = ({
|
|
|
376
311
|
kind: "init";
|
|
377
312
|
} & InitValidation) | ({
|
|
378
313
|
kind: "media";
|
|
379
|
-
} & MediaValidation)
|
|
380
|
-
|
|
314
|
+
} & MediaValidation);
|
|
315
|
+
/**
|
|
316
|
+
* The C2PA 2.4 golden-flow comparison of the embedded manifest against what the repository holds.
|
|
317
|
+
*/
|
|
318
|
+
type Golden = {
|
|
319
|
+
kind: "matches";
|
|
320
|
+
index: number;
|
|
321
|
+
} | {
|
|
322
|
+
kind: "differs";
|
|
323
|
+
index: number;
|
|
324
|
+
} | {
|
|
325
|
+
kind: "noneMatches";
|
|
326
|
+
candidates: number[];
|
|
327
|
+
} | {
|
|
328
|
+
kind: "unreadable";
|
|
329
|
+
index: number;
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* The C2PA list\'s `type` of a soft binding algorithm.
|
|
333
|
+
*/
|
|
334
|
+
type SoftBindingType = "fingerprint" | "watermark";
|
|
335
|
+
/**
|
|
336
|
+
* The Soft Binding Resolution API route a discovery came through.
|
|
337
|
+
*/
|
|
338
|
+
type DiscoveryVia = {
|
|
339
|
+
kind: "byBinding";
|
|
340
|
+
value: Uint8Array;
|
|
341
|
+
} | {
|
|
342
|
+
kind: "byContent";
|
|
343
|
+
hint?: Hint;
|
|
344
|
+
} | {
|
|
345
|
+
kind: "byReference";
|
|
346
|
+
hint?: Hint;
|
|
381
347
|
};
|
|
382
348
|
/**
|
|
383
|
-
*
|
|
349
|
+
* The evidence that singled a recovered verdict out.
|
|
350
|
+
*/
|
|
351
|
+
type VerdictRule = "onlyCandidate" | "notSuperseded" | "hardBinding";
|
|
352
|
+
/**
|
|
353
|
+
* The query a repository answers from the content: `matches/byReference` when `reference` is
|
|
354
|
+
* stated, so nothing is uploaded, else `matches/byContent` with the asset in the request.
|
|
355
|
+
*/
|
|
356
|
+
interface Content {
|
|
357
|
+
when: ContentWhen;
|
|
358
|
+
/**
|
|
359
|
+
* Where each repository downloads the asset from.
|
|
360
|
+
*/
|
|
361
|
+
reference?: Reference;
|
|
362
|
+
/**
|
|
363
|
+
* The largest asset an upload sends, in bytes; a larger one is reported `tooLarge`. Absent,
|
|
364
|
+
* 64 MiB.
|
|
365
|
+
*/
|
|
366
|
+
maxUploadBytes?: number;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* The re-sign chain between the returned credentials, by manifest label.
|
|
370
|
+
*/
|
|
371
|
+
interface Lineage {
|
|
372
|
+
supersedes: string[];
|
|
373
|
+
supersededBy: string[];
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* The value a content query was hinted with, under its own algorithm.
|
|
377
|
+
*/
|
|
378
|
+
interface Hint {
|
|
379
|
+
alg: string;
|
|
380
|
+
value: Uint8Array;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Timing a media segment\'s container carries.
|
|
384
384
|
*/
|
|
385
385
|
interface SegmentTiming {
|
|
386
386
|
/**
|
|
387
|
-
*
|
|
387
|
+
* The segment\'s `sequenceNumber`, a `bigint` as in the Node FFI lane.
|
|
388
388
|
*/
|
|
389
|
-
|
|
389
|
+
sequence: bigint;
|
|
390
390
|
/**
|
|
391
|
-
*
|
|
391
|
+
* The span its C2PA `emsg` covers, in milliseconds.
|
|
392
392
|
*/
|
|
393
|
-
|
|
393
|
+
duration?: number;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* What a stream verifier trusts, and how far a segment\'s clock may drift.
|
|
397
|
+
*/
|
|
398
|
+
interface StreamVerifierOptions {
|
|
399
|
+
trust: Trust;
|
|
400
|
+
/**
|
|
401
|
+
* How far a segment\'s presentation time may sit outside its session key\'s validity period,
|
|
402
|
+
* in milliseconds. Absent, 5 minutes.
|
|
403
|
+
*/
|
|
404
|
+
skewTolerance?: number;
|
|
394
405
|
/**
|
|
395
|
-
*
|
|
406
|
+
* Exact HTTPS origins approved for external live-video manifest recovery.
|
|
396
407
|
*/
|
|
397
|
-
|
|
408
|
+
manifestOrigins?: string[];
|
|
398
409
|
}
|
|
399
410
|
/**
|
|
400
|
-
* What
|
|
401
|
-
* itself, decided into `matches/byBinding`, and one field per content operation, absent when
|
|
402
|
-
* not to be called. It needs a configured repository and at least one query.
|
|
411
|
+
* What a verifier trusts. An omitted list trusts nothing.
|
|
403
412
|
*/
|
|
404
|
-
interface
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
413
|
+
interface Trust {
|
|
414
|
+
/**
|
|
415
|
+
* PEM anchors for the manifest signers the caller trusts.
|
|
416
|
+
*/
|
|
417
|
+
anchors?: string[];
|
|
418
|
+
/**
|
|
419
|
+
* PEM anchors for the time-stamping authorities the caller trusts.
|
|
420
|
+
*/
|
|
421
|
+
tsaAnchors?: string[];
|
|
422
|
+
/**
|
|
423
|
+
* Also trust the bundled official C2PA manifest and TSA lists, beside the caller\'s.
|
|
424
|
+
*/
|
|
425
|
+
c2pa: boolean;
|
|
426
|
+
/**
|
|
427
|
+
* Issuer DIDs whose CAWG identity (ICA) credentials count as validated, matched exactly
|
|
428
|
+
* against the credential issuer. Empty trusts no issuer: every identity assertion then
|
|
429
|
+
* reports `cawg.ica.untrusted_issuer` and withholds `cawg.ica.credential_valid`, which leaves
|
|
430
|
+
* the manifest\'s own validity untouched.
|
|
431
|
+
*/
|
|
432
|
+
icaIssuers?: string[];
|
|
409
433
|
}
|
|
410
434
|
/**
|
|
411
|
-
*
|
|
435
|
+
* What an asset verifier trusts and which repositories it may ask. An omitted list trusts or
|
|
436
|
+
* asks nothing.
|
|
412
437
|
*/
|
|
413
|
-
|
|
438
|
+
interface AssetVerifierOptions {
|
|
439
|
+
/**
|
|
440
|
+
* The C2PA manifest repositories recovery asks, each a Soft Binding Resolution API declared
|
|
441
|
+
* for exactly the algorithms it may be asked for. Results merge by manifest, and a match\'s
|
|
442
|
+
* `endpoint` is fetched from only when it names one of these. Empty: no recovery can be
|
|
443
|
+
* asked of this verifier.
|
|
444
|
+
*/
|
|
445
|
+
repositories?: Repository[];
|
|
446
|
+
trust: Trust;
|
|
447
|
+
}
|
|
414
448
|
/**
|
|
415
|
-
*
|
|
449
|
+
* What one verify may do to recover a manifest, as data: the soft bindings this client looks up
|
|
450
|
+
* itself through `matches/byBinding`, and the content query, absent when not to be asked. It
|
|
451
|
+
* needs a configured repository and at least one query.
|
|
416
452
|
*/
|
|
417
|
-
|
|
453
|
+
interface Recovery {
|
|
454
|
+
when: RecoveryTrigger;
|
|
455
|
+
softBindings?: SoftBindingSource[];
|
|
456
|
+
content?: Content;
|
|
457
|
+
/**
|
|
458
|
+
* The whole recovery\'s budget in milliseconds, every repository together, each request
|
|
459
|
+
* bounded by what remains. Absent, 10 minutes; at most 2147483647.
|
|
460
|
+
*/
|
|
461
|
+
timeout?: number;
|
|
462
|
+
}
|
|
418
463
|
/**
|
|
419
|
-
*
|
|
464
|
+
* What this verify concludes about the asset, from signed evidence alone.
|
|
420
465
|
*/
|
|
421
|
-
type
|
|
466
|
+
type Verdict = {
|
|
467
|
+
kind: "unsigned";
|
|
468
|
+
} | {
|
|
469
|
+
kind: "inconclusive";
|
|
470
|
+
} | {
|
|
471
|
+
kind: "embedded";
|
|
472
|
+
} | {
|
|
473
|
+
kind: "invalid";
|
|
474
|
+
index: number;
|
|
475
|
+
} | {
|
|
476
|
+
kind: "recovered";
|
|
477
|
+
index: number;
|
|
478
|
+
decidedBy: VerdictRule;
|
|
479
|
+
} | {
|
|
480
|
+
kind: "recoveredDerivative";
|
|
481
|
+
index: number;
|
|
482
|
+
decidedBy: VerdictRule;
|
|
483
|
+
} | {
|
|
484
|
+
kind: "ambiguous";
|
|
485
|
+
candidates: number[];
|
|
486
|
+
};
|
|
422
487
|
/**
|
|
423
|
-
*
|
|
424
|
-
* `@contentauth/c2pa-types`, the shape a credential\'s actions carry.
|
|
488
|
+
* When a verify asks the repositories.
|
|
425
489
|
*/
|
|
426
|
-
|
|
427
|
-
after: ContentTrigger;
|
|
428
|
-
url: string;
|
|
429
|
-
length: number;
|
|
430
|
-
mediaType?: string;
|
|
431
|
-
region: import('@contentauth/c2pa-types').Range[];
|
|
432
|
-
}
|
|
490
|
+
type RecoveryTrigger = "manifestMissing" | "always";
|
|
433
491
|
/**
|
|
434
|
-
*
|
|
435
|
-
* credential carries different evidence. Lane-local for the same reason [`FingerprintCheck`] is: a
|
|
436
|
-
* tag layout is what `#[binding(wasm)]` declines to express.
|
|
492
|
+
* Where a credential came from: embedded in the asset, or recovered from a repository.
|
|
437
493
|
*/
|
|
438
494
|
type CredentialOrigin = {
|
|
439
495
|
kind: "embedded";
|
|
440
496
|
} | {
|
|
441
497
|
kind: "recovered";
|
|
442
|
-
discoveries:
|
|
498
|
+
discoveries: Discovery[];
|
|
443
499
|
fingerprintCheck: FingerprintCheck;
|
|
444
500
|
};
|
|
445
501
|
/**
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
|
|
502
|
+
* Where one byBinding query\'s value comes from. A browser has no host engine: a vendor\'s
|
|
503
|
+
* detector runs repository-side, through `byContent`.
|
|
504
|
+
*/
|
|
505
|
+
type SoftBindingSource = {
|
|
506
|
+
kind: "builtin";
|
|
507
|
+
alg: string;
|
|
508
|
+
} | {
|
|
509
|
+
kind: "held";
|
|
510
|
+
alg: string;
|
|
511
|
+
value: Uint8Array;
|
|
512
|
+
};
|
|
513
|
+
/**
|
|
514
|
+
* Whether a code is a success, an informational note, or a failure.
|
|
515
|
+
*/
|
|
516
|
+
type ValidationCodeKind = "success" | "informational" | "failure";
|
|
517
|
+
/**
|
|
518
|
+
* Whether a content form runs on this verify. Judged against the byBinding results alone.
|
|
519
|
+
*/
|
|
520
|
+
type ContentWhen = "bindingMisses" | "always";
|
|
521
|
+
/**
|
|
522
|
+
* Whether the asset\'s own fingerprint backs up a manifest that a watermark led to.
|
|
449
523
|
*/
|
|
450
524
|
type FingerprintCheck = {
|
|
451
525
|
kind: "notNeeded";
|
|
452
526
|
} | {
|
|
453
|
-
kind: "
|
|
527
|
+
kind: "missing";
|
|
454
528
|
} | {
|
|
455
529
|
kind: "unsupported";
|
|
456
|
-
|
|
530
|
+
alg: string;
|
|
457
531
|
} | {
|
|
458
532
|
kind: "indeterminate";
|
|
459
533
|
} | {
|
|
@@ -461,59 +535,40 @@ type FingerprintCheck = {
|
|
|
461
535
|
score: number;
|
|
462
536
|
};
|
|
463
537
|
/**
|
|
464
|
-
*
|
|
538
|
+
* Whether the manifest\'s hard binding holds over the bytes this verify read.
|
|
465
539
|
*/
|
|
466
|
-
type HardBinding = "match" | "mismatch";
|
|
540
|
+
type HardBinding = "match" | "mismatch" | "unverified";
|
|
467
541
|
/**
|
|
468
|
-
*
|
|
469
|
-
*/
|
|
470
|
-
interface Lineage {
|
|
471
|
-
supersedes: string[];
|
|
472
|
-
supersededBy: string[];
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* [`crate::asset::RecoveryIssue`] as JS sees it: a tagged union, each kind with its own data.
|
|
542
|
+
* Why repository recovery did not complete cleanly, or why one candidate was omitted.
|
|
476
543
|
*/
|
|
477
544
|
type RecoveryIssue = {
|
|
478
|
-
kind: "
|
|
479
|
-
|
|
545
|
+
kind: "computeFailed";
|
|
546
|
+
alg: string;
|
|
480
547
|
message: string;
|
|
481
548
|
} | {
|
|
482
|
-
kind: "
|
|
483
|
-
algorithm: string;
|
|
484
|
-
} | {
|
|
485
|
-
kind: "bindingUndeclared";
|
|
486
|
-
binderIndex: number;
|
|
487
|
-
algorithm: string;
|
|
488
|
-
} | {
|
|
489
|
-
kind: "bindingQueryFailed";
|
|
549
|
+
kind: "bindingFailed";
|
|
490
550
|
repository: string;
|
|
491
|
-
|
|
492
|
-
algorithm: string;
|
|
551
|
+
alg: string;
|
|
493
552
|
message: string;
|
|
494
553
|
} | {
|
|
495
554
|
kind: "queryRefused";
|
|
496
555
|
repository: string;
|
|
497
|
-
|
|
498
|
-
message: string;
|
|
499
|
-
} | {
|
|
500
|
-
kind: "contentFormUnsupported";
|
|
501
|
-
repository: string;
|
|
556
|
+
alg: string;
|
|
502
557
|
message: string;
|
|
503
558
|
} | {
|
|
504
|
-
kind: "
|
|
559
|
+
kind: "contentFailed";
|
|
505
560
|
repository: string;
|
|
506
|
-
|
|
561
|
+
alg: string;
|
|
507
562
|
message: string;
|
|
508
563
|
} | {
|
|
509
564
|
kind: "capabilitiesUnavailable";
|
|
510
565
|
repository: string;
|
|
511
566
|
message: string;
|
|
512
567
|
} | {
|
|
513
|
-
kind: "
|
|
514
|
-
|
|
568
|
+
kind: "tooLarge";
|
|
569
|
+
maxUploadBytes: number;
|
|
515
570
|
} | {
|
|
516
|
-
kind: "
|
|
571
|
+
kind: "fetchFailed";
|
|
517
572
|
repository: string;
|
|
518
573
|
manifestId: string;
|
|
519
574
|
message: string;
|
|
@@ -527,98 +582,22 @@ type RecoveryIssue = {
|
|
|
527
582
|
manifestId: string;
|
|
528
583
|
endpoint: string;
|
|
529
584
|
} | {
|
|
530
|
-
kind: "
|
|
585
|
+
kind: "limitReached";
|
|
531
586
|
message: string;
|
|
532
587
|
};
|
|
533
|
-
/**
|
|
534
|
-
* [`crate::asset::VerdictRule`] as JS sees it.
|
|
535
|
-
*/
|
|
536
|
-
type VerdictRule = "onlyCandidate" | "notSuperseded" | "hardBinding";
|
|
537
|
-
/**
|
|
538
|
-
* [`crate::asset::Verdict`] as JS sees it.
|
|
539
|
-
*/
|
|
540
|
-
type Verdict = {
|
|
541
|
-
kind: "unsigned";
|
|
542
|
-
} | {
|
|
543
|
-
kind: "inconclusive";
|
|
544
|
-
} | {
|
|
545
|
-
kind: "embedded";
|
|
546
|
-
} | {
|
|
547
|
-
kind: "recovered";
|
|
548
|
-
index: number;
|
|
549
|
-
decidedBy: VerdictRule;
|
|
550
|
-
} | {
|
|
551
|
-
kind: "recoveredDerivative";
|
|
552
|
-
index: number;
|
|
553
|
-
decidedBy: VerdictRule;
|
|
554
|
-
} | {
|
|
555
|
-
kind: "ambiguous";
|
|
556
|
-
candidates: number[];
|
|
557
|
-
};
|
|
558
|
-
/**
|
|
559
|
-
* `matches/byContent`: the asset is uploaded to each repository, one request per algorithm that
|
|
560
|
-
* repository is declared for.
|
|
561
|
-
*/
|
|
562
|
-
interface ByContent {
|
|
563
|
-
after: ContentTrigger;
|
|
564
|
-
}
|
|
565
588
|
interface AssetVerification {
|
|
566
589
|
credentials: Credential[];
|
|
567
590
|
recovery: RecoverySummary;
|
|
568
|
-
|
|
591
|
+
/**
|
|
592
|
+
* Absent when there was nothing to compare.
|
|
593
|
+
*/
|
|
594
|
+
golden?: Golden;
|
|
569
595
|
verdict: Verdict;
|
|
570
596
|
}
|
|
571
597
|
interface RecoverySummary {
|
|
572
598
|
status: RecoveryStatus;
|
|
573
599
|
issues: RecoveryIssue[];
|
|
574
600
|
}
|
|
575
|
-
type ContentBindingClass = "fingerprint" | "watermark";
|
|
576
|
-
type GoldenComparison = {
|
|
577
|
-
kind: "notRequested";
|
|
578
|
-
} | {
|
|
579
|
-
kind: "noEmbeddedManifest";
|
|
580
|
-
} | {
|
|
581
|
-
kind: "noRecoveredManifest";
|
|
582
|
-
} | {
|
|
583
|
-
kind: "recoveryIncomplete";
|
|
584
|
-
} | {
|
|
585
|
-
kind: "matches";
|
|
586
|
-
recoveredIndex: number;
|
|
587
|
-
} | {
|
|
588
|
-
kind: "differs";
|
|
589
|
-
recoveredIndex: number;
|
|
590
|
-
} | {
|
|
591
|
-
kind: "noneMatches";
|
|
592
|
-
candidates: number[];
|
|
593
|
-
} | {
|
|
594
|
-
kind: "unreadable";
|
|
595
|
-
recoveredIndex: number;
|
|
596
|
-
};
|
|
597
|
-
type RecoveryDiscovery = {
|
|
598
|
-
kind: "byBinding";
|
|
599
|
-
class: ContentBindingClass;
|
|
600
|
-
binding: SoftBinding;
|
|
601
|
-
binderIndex: number;
|
|
602
|
-
repositoryScore: number | undefined;
|
|
603
|
-
repository: string;
|
|
604
|
-
fetchedFrom: string;
|
|
605
|
-
} | {
|
|
606
|
-
kind: "byContent";
|
|
607
|
-
hint: SoftBinding | undefined;
|
|
608
|
-
class: ContentBindingClass;
|
|
609
|
-
algorithm: string;
|
|
610
|
-
repositoryScore: number | undefined;
|
|
611
|
-
repository: string;
|
|
612
|
-
fetchedFrom: string;
|
|
613
|
-
} | {
|
|
614
|
-
kind: "byReference";
|
|
615
|
-
hint: SoftBinding | undefined;
|
|
616
|
-
class: ContentBindingClass;
|
|
617
|
-
algorithm: string;
|
|
618
|
-
repositoryScore: number | undefined;
|
|
619
|
-
repository: string;
|
|
620
|
-
fetchedFrom: string;
|
|
621
|
-
};
|
|
622
601
|
type RecoveryStatus = "notRequested" | "notFound" | "recovered" | "incomplete";
|
|
623
602
|
declare class AssetVerifier {
|
|
624
603
|
private constructor();
|
|
@@ -633,19 +612,17 @@ declare class AssetVerifier {
|
|
|
633
612
|
/**
|
|
634
613
|
* Verify an asset against the configured trust anchors and per-call recovery options.
|
|
635
614
|
*
|
|
636
|
-
* Reads the C2PA
|
|
637
|
-
*
|
|
615
|
+
* Reads the C2PA handlers included in the browser build. Additional native modules require
|
|
616
|
+
* the Node or Python SDK.
|
|
617
|
+
* `format` optionally declares the media type for inputs such as SVG and plain text.
|
|
638
618
|
*
|
|
639
619
|
* # Errors
|
|
640
620
|
*
|
|
641
|
-
* Throws on a malformed `
|
|
621
|
+
* Throws on a malformed `source`, a repository (or engine) failure, or a validation
|
|
642
622
|
* failure.
|
|
643
623
|
*/
|
|
644
|
-
verify(
|
|
624
|
+
verify(source: RangeSource, recovery?: Recovery | null, format?: string | null): Promise<Verification>;
|
|
645
625
|
}
|
|
646
|
-
declare function C2PA_TRUST_LIST(): string;
|
|
647
|
-
declare function C2PA_TSA_TRUST_LIST(): string;
|
|
648
|
-
declare function DEV_CA(): string;
|
|
649
626
|
/**
|
|
650
627
|
* One stream being validated. It owns the session keys and manifest ids its init segments
|
|
651
628
|
* advertised, so releasing the stream is dropping this object.
|
|
@@ -655,8 +632,8 @@ declare class StreamSession {
|
|
|
655
632
|
free(): void;
|
|
656
633
|
[Symbol.dispose](): void;
|
|
657
634
|
/**
|
|
658
|
-
*
|
|
659
|
-
* `StreamVerifier.resume` from.
|
|
635
|
+
* This stream's id and everything its init segments have registered, as CBOR for another
|
|
636
|
+
* node to `StreamVerifier.resume` from.
|
|
660
637
|
*
|
|
661
638
|
* The one piece of stream state that leaves the SDK, and only because a clustered
|
|
662
639
|
* verifier needs it: the init URL is overwritten on rotation, so a node joining during
|
|
@@ -677,7 +654,7 @@ declare class StreamSession {
|
|
|
677
654
|
* Throws an `SdkError` on parse or signature failure, or when a media segment arrives
|
|
678
655
|
* before any init was processed for the stream.
|
|
679
656
|
*/
|
|
680
|
-
validate(
|
|
657
|
+
validate(source: RangeSource): Promise<SegmentValidation>;
|
|
681
658
|
}
|
|
682
659
|
declare class StreamVerifier {
|
|
683
660
|
private constructor();
|
|
@@ -692,25 +669,57 @@ declare class StreamVerifier {
|
|
|
692
669
|
*/
|
|
693
670
|
static create(options: StreamVerifierOptions): StreamVerifier;
|
|
694
671
|
/**
|
|
695
|
-
* Open `
|
|
672
|
+
* Open the stream `id` for validation, handing back a `StreamSession` to feed segments to.
|
|
696
673
|
*
|
|
697
674
|
* No I/O: the handle carries the id so it cannot be mistyped or confused with another
|
|
698
675
|
* stream's, and classification still happens per segment. Opening one id twice hands
|
|
699
676
|
* back the same live session, so a component that remounts keeps the state its earlier
|
|
700
677
|
* handle accumulated.
|
|
701
678
|
*/
|
|
702
|
-
open(
|
|
679
|
+
open(id: string): StreamSession;
|
|
703
680
|
/**
|
|
704
|
-
* Open
|
|
705
|
-
*
|
|
681
|
+
* Open the stream another node exported, its state merged into whatever this one holds
|
|
682
|
+
* for that stream already.
|
|
706
683
|
*
|
|
707
684
|
* # Errors
|
|
708
685
|
*
|
|
709
|
-
* Throws an `SdkError`
|
|
710
|
-
* `StreamSession.export` produced, or
|
|
686
|
+
* Throws an `SdkError` with a field violation at `state` when it is not a value
|
|
687
|
+
* `StreamSession.export` produced (`state.malformed`), or one of another export version
|
|
688
|
+
* (`state.version`).
|
|
711
689
|
*/
|
|
712
|
-
resume(
|
|
690
|
+
resume(state: Uint8Array): Promise<StreamSession>;
|
|
713
691
|
}
|
|
692
|
+
/**
|
|
693
|
+
* One `verify` result held with the stores it read: `report` is the data, and `resource` reads a
|
|
694
|
+
* thumbnail from credential `credential` (its position in `report.credentials`) by the
|
|
695
|
+
* `identifier` of a resource reference in its manifest. A class rather than a field of the
|
|
696
|
+
* report because a store cannot be serialized, and one handle per verify is what a worker can
|
|
697
|
+
* proxy (a class nested in the report cannot cross a thread).
|
|
698
|
+
*/
|
|
699
|
+
declare class Verification {
|
|
700
|
+
private constructor();
|
|
701
|
+
free(): void;
|
|
702
|
+
[Symbol.dispose](): void;
|
|
703
|
+
/**
|
|
704
|
+
* The bytes of one resource credential `credential` holds, or `undefined`.
|
|
705
|
+
*
|
|
706
|
+
* # Errors
|
|
707
|
+
*
|
|
708
|
+
* Throws `READER_INVALID` when the store holds the resource but cannot produce it, and
|
|
709
|
+
* `undefined` for a `credential` out of range.
|
|
710
|
+
*/
|
|
711
|
+
resource(credential: number, uri: string): Uint8Array | undefined;
|
|
712
|
+
/**
|
|
713
|
+
* The report: credentials, recovery, golden flow and verdict.
|
|
714
|
+
*/
|
|
715
|
+
readonly report: AssetVerification;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* PEM trust anchor for the Limbo Integrity development signing environment, **development
|
|
719
|
+
* only**, no security guarantees: put it in `trust.anchors` for a development build, never in a
|
|
720
|
+
* release.
|
|
721
|
+
*/
|
|
722
|
+
declare function devCa(): string;
|
|
714
723
|
//#endregion
|
|
715
724
|
//#region src/worker-thread.d.ts
|
|
716
725
|
/**
|
|
@@ -737,9 +746,18 @@ declare abstract class Handle<T extends {
|
|
|
737
746
|
constructor(inner: T);
|
|
738
747
|
[finalizer](): void;
|
|
739
748
|
}
|
|
749
|
+
/**
|
|
750
|
+
* One verify result. A wasm class cannot cross the thread, so the report and the stores behind it
|
|
751
|
+
* stay here and the caller holds this: `report()` is the data, `resource()` reads a thumbnail from
|
|
752
|
+
* a credential by its position in `report().credentials`.
|
|
753
|
+
*/
|
|
754
|
+
declare class VerificationHandle extends Handle<Verification> {
|
|
755
|
+
report(): AssetVerification;
|
|
756
|
+
resource(credential: number, uri: string): Uint8Array | undefined;
|
|
757
|
+
}
|
|
740
758
|
declare class AssetVerifierHandle extends Handle<AssetVerifier> {
|
|
741
759
|
/** `recovery` is what this verify may do to recover a manifest, as the direct import takes it. */
|
|
742
|
-
verify(asset: Asset, recovery: Recovery | undefined): Promise<
|
|
760
|
+
verify(asset: Asset, recovery: Recovery | undefined, format?: string): Promise<VerificationHandle & ProxyMarked>;
|
|
743
761
|
}
|
|
744
762
|
/** One stream being validated. Dropping the handle releases the session it accumulated. */
|
|
745
763
|
declare class StreamSessionHandle extends Handle<StreamSession> {
|
|
@@ -747,8 +765,8 @@ declare class StreamSessionHandle extends Handle<StreamSession> {
|
|
|
747
765
|
export(): Uint8Array;
|
|
748
766
|
}
|
|
749
767
|
declare class StreamVerifierHandle extends Handle<StreamVerifier> {
|
|
750
|
-
open(
|
|
751
|
-
resume(
|
|
768
|
+
open(id: string): StreamSessionHandle & ProxyMarked;
|
|
769
|
+
resume(state: Uint8Array): Promise<StreamSessionHandle & ProxyMarked>;
|
|
752
770
|
}
|
|
753
771
|
/** The module's own surface, name for name with the direct import. */
|
|
754
772
|
declare const sdk: {
|
|
@@ -763,13 +781,11 @@ declare const sdk: {
|
|
|
763
781
|
StreamVerifier: {
|
|
764
782
|
create: (options: StreamVerifierOptions) => StreamVerifierHandle & ProxyMarked;
|
|
765
783
|
} & ProxyMarked;
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
derive: (spec: BinderSpec, content: Asset, options: DeriveOptions) => Promise<SoftBinding | undefined>;
|
|
772
|
-
} & ProxyMarked;
|
|
784
|
+
/**
|
|
785
|
+
* The values this SDK computes for `alg` over the asset, `[]` when it finds none. `format` is the
|
|
786
|
+
* asset's media type; omitted, the bytes name it.
|
|
787
|
+
*/
|
|
788
|
+
computeSoftBinding(alg: string, asset: Asset, format?: string): Promise<Block[]>;
|
|
773
789
|
/**
|
|
774
790
|
* Read a detached manifest store. Contents, not a verdict: with no asset there is no hard binding
|
|
775
791
|
* to check, so the store's validation fields state nothing this established.
|
|
@@ -780,14 +796,7 @@ declare const sdk: {
|
|
|
780
796
|
* manifest's claim thumbnail, and any ingredient's.
|
|
781
797
|
*/
|
|
782
798
|
resource(manifest: Asset, uri: string): Promise<Uint8Array<ArrayBufferLike> | undefined>;
|
|
783
|
-
|
|
784
|
-
* Every thumbnail the store references, by the identifier it references them under. One parse
|
|
785
|
-
* and one thread hop for the whole set, where `resource` pays both per call.
|
|
786
|
-
*/
|
|
787
|
-
thumbnails(manifest: Asset): Promise<Record<string, Uint8Array<ArrayBufferLike>>>;
|
|
788
|
-
C2PA_TRUST_LIST: typeof C2PA_TRUST_LIST;
|
|
789
|
-
C2PA_TSA_TRUST_LIST: typeof C2PA_TSA_TRUST_LIST;
|
|
790
|
-
DEV_CA: typeof DEV_CA;
|
|
799
|
+
devCa: typeof devCa;
|
|
791
800
|
close(): void;
|
|
792
801
|
};
|
|
793
802
|
/** What the caller's thread holds a `Comlink.Remote` of. */
|