@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.
@@ -163,141 +163,61 @@ interface RangeSource {
163
163
  readAt: (offset: number, length: number) => Uint8Array;
164
164
  }
165
165
  /**
166
- * A C2PA soft binding: an algorithm id (from the C2PA soft-binding algorithm
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 SoftBinding {
173
- /**
174
- * C2PA soft-binding algorithm id, e.g. `io.iscc.v0`.
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 binder spelled as data, so it crosses into a worker as well as the direct import: the
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
- type BinderSpec = {
189
- kind: "iscc";
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
- * C2PA validation state of a manifest (spec §14.3).
179
+ * A `soft-binding-timespan-map`: where the range starts in the media and how long it lasts, in
180
+ * milliseconds.
209
181
  */
210
- type ValidationState = "Invalid" | "Valid" | "Trusted";
182
+ interface Timespan {
183
+ start: number;
184
+ duration: number;
185
+ }
211
186
  /**
212
- * Construction options for [`AssetVerifier::new`] (and the `AssetVerifier.create` JS
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 AssetVerifierOptions {
189
+ interface SessionKey {
220
190
  /**
221
- * The C2PA manifest repositories recovery asks, each a Soft Binding Resolution API declared
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
- trustC2paAnchors: boolean;
193
+ kid: Uint8Array;
240
194
  /**
241
- * Issuer DIDs whose CAWG identity (ICA) credentials count as validated, matched
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
- trustedIcaIssuers: string[];
197
+ publicKey: Uint8Array;
247
198
  }
248
199
  /**
249
- * Construction options for [`StreamVerifier::new`] (and the `StreamVerifier.create`
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 StreamVerifierOptions {
257
- /**
258
- * PEM trust anchors for the manifest signers the caller trusts.
259
- */
260
- trustAnchors: string[];
202
+ interface Reference {
261
203
  /**
262
- * PEM trust anchors for the time-stamping authorities the caller trusts.
204
+ * A short-lived https URL without credentials.
263
205
  */
264
- tsaTrustAnchors: string[];
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
- * Issuer DIDs whose CAWG identity (ICA) credentials count as validated, matched
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
- trustedIcaIssuers: string[];
210
+ length: number;
277
211
  /**
278
- * How far a segment\'s timestamp may sit from wall-clock before it is rejected as
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
- segmentSkewToleranceSecs: number;
214
+ format?: string;
215
+ ranges?: import('@contentauth/c2pa-types').Range[];
283
216
  }
284
217
  /**
285
- * Everything one `derive` needs beyond the asset: how its format is known. The same record
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 AssetFormat = {
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: "listed";
310
- algorithm: string;
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
- * The bytes behind every thumbnail the manifests reference, by that reference\'s
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. See [`crate::asset::Lineage`].
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
- valid: boolean;
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
- keyId: Uint8Array;
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: SessionKeySummary[];
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
- kind: "unknown";
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
- * Timing facts carried by a media segment\'s container.
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
- * Media segment sequence number (exact below 2^53).
387
+ * The segment\'s `sequenceNumber`, a `bigint` as in the Node FFI lane.
388
388
  */
389
- sequenceNumber: number;
389
+ sequence: bigint;
390
390
  /**
391
- * MP4 timescale (ticks per second) for this segment\'s timing, if present.
391
+ * The span its C2PA `emsg` covers, in milliseconds.
392
392
  */
393
- timescale?: number;
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
- * Segment duration in seconds, if the container reports it.
406
+ * Exact HTTPS origins approved for external live-video manifest recovery.
396
407
  */
397
- eventDurationSecs?: number;
408
+ manifestOrigins?: string[];
398
409
  }
399
410
  /**
400
- * What one verify may do to recover a manifest, as data: the binders this client derives for
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 Recovery {
405
- when: RecoveryTrigger;
406
- binders: BinderSpec[];
407
- byContent?: ByContent;
408
- byReference?: ByReference;
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
- * When [`AssetVerifier::verify_asset`] queries the repository.
435
+ * What an asset verifier trusts and which repositories it may ask. An omitted list trusts or
436
+ * asks nothing.
412
437
  */
413
- type RecoveryTrigger = "manifestMissing" | "always";
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
- * Whether a code is a success, an informational note, or a failure.
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
- type ValidationCodeKind = "success" | "informational" | "failure";
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
- * Whether a content form runs on this verify. Judged against the byBinding results alone.
464
+ * What this verify concludes about the asset, from signed evidence alone.
420
465
  */
421
- type ContentTrigger = "byBindingMisses" | "always";
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
- * [`crate::asset::ByReference`] as JS states it: the region is the `Range` of
424
- * `@contentauth/c2pa-types`, the shape a credential\'s actions carry.
488
+ * When a verify asks the repositories.
425
489
  */
426
- interface ByReference {
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
- * [`crate::asset::CredentialOrigin`] as JS sees it: a tagged union, since each way of finding a
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: RecoveryDiscovery[];
498
+ discoveries: Discovery[];
443
499
  fingerprintCheck: FingerprintCheck;
444
500
  };
445
501
  /**
446
- * [`crate::asset::FingerprintCheck`] as JS sees it: a tagged union, since `compared` carries a
447
- * measurement the other two do not. Lane-local rather than `#[binding(wasm)]` on the core,
448
- * because a tag layout is exactly what that macro declines to express.
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: "nothingToCompare";
527
+ kind: "missing";
454
528
  } | {
455
529
  kind: "unsupported";
456
- algorithm: string;
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
- * [`crate::asset::HardBinding`] as JS sees it.
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
- * [`crate::asset::Lineage`] as JS sees it.
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: "binderFailed";
479
- binderIndex: number;
545
+ kind: "computeFailed";
546
+ alg: string;
480
547
  message: string;
481
548
  } | {
482
- kind: "algorithmDeprecated";
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
- binderIndex: number;
492
- algorithm: string;
551
+ alg: string;
493
552
  message: string;
494
553
  } | {
495
554
  kind: "queryRefused";
496
555
  repository: string;
497
- algorithm: string;
498
- message: string;
499
- } | {
500
- kind: "contentFormUnsupported";
501
- repository: string;
556
+ alg: string;
502
557
  message: string;
503
558
  } | {
504
- kind: "contentQueryFailed";
559
+ kind: "contentFailed";
505
560
  repository: string;
506
- algorithm: string;
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: "contentTooLarge";
514
- capBytes: number;
568
+ kind: "tooLarge";
569
+ maxUploadBytes: number;
515
570
  } | {
516
- kind: "candidateFetchFailed";
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: "resourceLimitReached";
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
- goldenComparison: GoldenComparison;
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-native formats. A container format (MXF) is plugin-backed, and plugins
637
- * are native, so a master is verified through the native SDK.
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 `input`, a repository (or binder) failure, or a validation
621
+ * Throws on a malformed `source`, a repository (or engine) failure, or a validation
642
622
  * failure.
643
623
  */
644
- verify(input: RangeSource, recovery?: Recovery | null): Promise<AssetVerification>;
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
- * Everything this stream's init segments have registered, as CBOR for another node to
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(data: RangeSource): Promise<SegmentValidation>;
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 `stream_id` for validation, handing back a `StreamSession` to feed segments to.
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(stream_id: string): StreamSession;
679
+ open(id: string): StreamSession;
703
680
  /**
704
- * Open `stream_id` on the state another node exported, merged into whatever this one
705
- * holds for that id already.
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` (`STREAM_INVALID`) when `state` is not a value
710
- * `StreamSession.export` produced, or carries a version this SDK no longer reads.
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(stream_id: string, state: Uint8Array): StreamSession;
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<AssetVerification>;
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(streamId: string): StreamSessionHandle & ProxyMarked;
751
- resume(streamId: string, state: Uint8Array): StreamSessionHandle & ProxyMarked;
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
- Binder: {
767
- /**
768
- * Derive one binder's binding standalone. The binder is built, used and dropped here, so there
769
- * is no handle to keep: what the caller wants back is the binding.
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. */