Skip to content

feat: ecdsa and w3c data model 2.0#105

Merged
rongquan1 merged 22 commits into
mainfrom
release/v1-merge
Aug 25, 2025
Merged

feat: ecdsa and w3c data model 2.0#105
rongquan1 merged 22 commits into
mainfrom
release/v1-merge

Conversation

@rongquan1

@rongquan1 rongquan1 commented Aug 25, 2025

Copy link
Copy Markdown
Contributor

BREAKING CHANGE: ecdsa and w3c data model 2.0

Summary by CodeRabbit

  • New Features
    • Selective disclosure: deriveW3C and DocumentBuilder.derive for deriving credentials.
    • Signing updates: signW3C supports options (mandatoryPointers), defaults to ECDSA-SD-2023, and uses Multikey.
    • VC 2.0 support: validFrom/validUntil, DataIntegrityProof, updated contexts.
    • Verification: new ECDSA W3C integrity verifier with derive-on-verify behavior.
    • Utilities: added isObfuscated and getObfuscatedData helpers.
  • Documentation
    • Reorganized README; added deriving/verification flows, VC 2.0 examples, Multikey usage, and encrypt() signature.
  • Tests
    • Expanded coverage for VC 2.0, ECDSA-SD-2023, derivation, and verification.
  • Chores
    • Dependencies updated to 1.3.0-alpha; added @trustvc/w3c.

nghaninn and others added 22 commits June 30, 2025 10:16
* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

---------

Co-authored-by: RishabhS7 <59636880+RishabhS7@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
## [1.6.0-alpha.1](v1.5.3...v1.6.0-alpha.1) (2025-06-30)

### Features

* token registry functions ([#74](#74)) ([5690fcd](5690fcd))

### Miscellaneous Chores

* back merge ([#75](#75)) ([7cc1891](7cc1891)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73)
* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: add transfer holder function

* feat: add transfer owners beneficiary

* chore: tests cleanup

* chore: tests cleanup

* fix: remove console

* fix: rever useendorement chain

* fix: remove console

* feat: add reject transfer functions

* chore: trigger rebuild after rebase

* chore(release): 1.5.4 [skip ci]

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* feat: add transfer holder function

* feat: add transfer owners beneficiary

* chore: tests cleanup

* fix: remove console

* fix: rever useendorement chain

* feat: add reject transfer functions

* chore: trigger rebuild after rebase

* chore: trigger rebuild after rebase

* feat: token registry return functions

* feat: add mint function

* fix: update fixes

* fix: update tests

* revert: revert changes

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* fix: update imports

* fix: update imports
## [1.6.0-alpha.2](v1.6.0-alpha.1...v1.6.0-alpha.2) (2025-07-15)

### Features

* mint function ([#78](#78)) ([2ea52ce](2ea52ce)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#72](#72)
* owner of function ([#79](#79)) ([81d0e36](81d0e36))
* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* chore: add e2e test for transfer functions

* chore: add e2e test for transfer functions

* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* chore: add e2e test for transfer functions

* chore: add e2e test for transfer functions

* fix: update mock tests

* fix: update mock test fixtures

* fix: update mock tests for mint and return

* fix: update test script

* fix: update imports

* fix: update gitignore

* fix: delete cache

* fix: update imports
* chore: e2e tests for reject functions

* fix: reject function ethers v6 compatible

* fix: update imports

* fix: mock test cases

* fix: import fixed
* chore: e2e tests for reject functions

* fix: reject function ethers v6 compatible

* fix: update imports

* fix: mock test cases

* fix: static call fixes

* chore: add e2e test cases

* fix: update imports

* fix: update imports

* fix: tests

* fix: mock functions

* fix: change name

* fix: update imports

* fix: update src imports
## [1.6.0-alpha.3](v1.6.0-alpha.2...v1.6.0-alpha.3) (2025-07-18)

### Bug Fixes

* e2e return token tests ([#84](#84)) ([703be01](703be01))

### Miscellaneous Chores

* e2e tests reject transfer ([#83](#83)) ([58a8da2](58a8da2))
* e2e transfers tests ([#82](#82)) ([145e763](145e763))
* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: support passing titleEscrowAddress to fetchEndorsementChain (#80)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0 [skip ci]

## [1.6.0](v1.5.5...v1.6.0) (2025-07-14)

### Features

* support passing titleEscrowAddress to fetchEndorsementChain ([#80](#80)) ([aa7b4f0](aa7b4f0))

* feat: add astron v5 (#81)

Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* chore(release): 1.7.0 [skip ci]

## [1.7.0](v1.6.0...v1.7.0) (2025-07-15)

### Features

* add astron v5 ([#81](#81)) ([0bebeae](0bebeae))

---------

Co-authored-by: RishabhS7 <59636880+RishabhS7@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
Co-authored-by: caict-develop-zhangbo <68949988+caict-develop-zhangbo@users.noreply.github.com>
Co-authored-by: maxufeng <maxufeng@caict.ac.cn>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
## [1.6.0-alpha.4](v1.6.0-alpha.3...v1.6.0-alpha.4) (2025-07-23)

### Bug Fixes

* trigger release ([#86](#86)) ([d2fb6fb](d2fb6fb))

### Miscellaneous Chores

* merge main into v1  ([#85](#85)) ([b81b422](b81b422)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#80](#80) [#80](#80) [#81](#81) [#81](#81)
* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: support passing titleEscrowAddress to fetchEndorsementChain (#80)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0 [skip ci]

## [1.6.0](v1.5.5...v1.6.0) (2025-07-14)

### Features

* support passing titleEscrowAddress to fetchEndorsementChain ([#80](#80)) ([aa7b4f0](aa7b4f0))

* feat: add astron v5 (#81)

Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* chore(release): 1.7.0 [skip ci]

## [1.7.0](v1.6.0...v1.7.0) (2025-07-15)

### Features

* add astron v5 ([#81](#81)) ([0bebeae](0bebeae))

* fix: update tradetrust-tt/tradetrust package (#87)

* fix: update tradetrust-tt/tradetrust package

* fix: update version

* fix: update imports

* chore(release): 1.7.1 [skip ci]

## [1.7.1](v1.7.0...v1.7.1) (2025-07-25)

### Bug Fixes

* update tradetrust-tt/tradetrust package ([#87](#87)) ([e4f75a4](e4f75a4))

* fix: upgrade packages (#88)

* chore(release): 1.7.2 [skip ci]

## [1.7.2](v1.7.1...v1.7.2) (2025-07-28)

### Bug Fixes

* upgrade packages ([#88](#88)) ([0cc314e](0cc314e))

* fix: error message types (#89)

* chore(release): 1.7.3 [skip ci]

## [1.7.3](v1.7.2...v1.7.3) (2025-07-28)

### Bug Fixes

* error message types ([#89](#89)) ([d83bada](d83bada))

* fix: upgrade packages (#90)

* chore(release): 1.7.4 [skip ci]

## [1.7.4](v1.7.3...v1.7.4) (2025-07-29)

### Bug Fixes

* upgrade packages ([#90](#90)) ([758651d](758651d))

---------

Co-authored-by: RishabhS7 <59636880+RishabhS7@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
Co-authored-by: caict-develop-zhangbo <68949988+caict-develop-zhangbo@users.noreply.github.com>
Co-authored-by: maxufeng <maxufeng@caict.ac.cn>
* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: support passing titleEscrowAddress to fetchEndorsementChain (#80)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0 [skip ci]

## [1.6.0](v1.5.5...v1.6.0) (2025-07-14)

### Features

* support passing titleEscrowAddress to fetchEndorsementChain ([#80](#80)) ([aa7b4f0](aa7b4f0))

* feat: add astron v5 (#81)

Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* chore(release): 1.7.0 [skip ci]

## [1.7.0](v1.6.0...v1.7.0) (2025-07-15)

### Features

* add astron v5 ([#81](#81)) ([0bebeae](0bebeae))

* fix: update tradetrust-tt/tradetrust package (#87)

* fix: update tradetrust-tt/tradetrust package

* fix: update version

* fix: update imports

* chore(release): 1.7.1 [skip ci]

## [1.7.1](v1.7.0...v1.7.1) (2025-07-25)

### Bug Fixes

* update tradetrust-tt/tradetrust package ([#87](#87)) ([e4f75a4](e4f75a4))

* fix: upgrade packages (#88)

* chore(release): 1.7.2 [skip ci]

## [1.7.2](v1.7.1...v1.7.2) (2025-07-28)

### Bug Fixes

* upgrade packages ([#88](#88)) ([0cc314e](0cc314e))

* fix: error message types (#89)

* chore(release): 1.7.3 [skip ci]

## [1.7.3](v1.7.2...v1.7.3) (2025-07-28)

### Bug Fixes

* error message types ([#89](#89)) ([d83bada](d83bada))

* fix: upgrade packages (#90)

* chore(release): 1.7.4 [skip ci]

## [1.7.4](v1.7.3...v1.7.4) (2025-07-29)

### Bug Fixes

* upgrade packages ([#90](#90)) ([758651d](758651d))

* feat: token registry functions (#96)

* chore(release): 1.8.0 [skip ci]

## [1.8.0](v1.7.4...v1.8.0) (2025-07-30)

### Features

* token registry functions ([#96](#96)) ([6c379e9](6c379e9))

* fix: accept return function (#97)

* chore(release): 1.8.1 [skip ci]

## [1.8.1](v1.8.0...v1.8.1) (2025-08-07)

### Bug Fixes

* accept return function ([#97](#97)) ([6398017](6398017))

* fix: update edsa w3c verifier

* fix: update vefiable doc v2.0

* feat: token registry functions (#74)

* chore(release): 1.6.0-alpha.1 [skip ci]

## [1.6.0-alpha.1](v1.5.3...v1.6.0-alpha.1) (2025-06-30)

### Features

* token registry functions ([#74](#74)) ([5690fcd](5690fcd))

### Miscellaneous Chores

* back merge ([#75](#75)) ([7cc1891](7cc1891)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73)

* feat: mint function (#78)

* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: add transfer holder function

* feat: add transfer owners beneficiary

* chore: tests cleanup

* chore: tests cleanup

* fix: remove console

* fix: rever useendorement chain

* fix: remove console

* feat: add reject transfer functions

* chore: trigger rebuild after rebase

* chore(release): 1.5.4 [skip ci]

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* feat: add transfer holder function

* feat: add transfer owners beneficiary

* chore: tests cleanup

* fix: remove console

* fix: rever useendorement chain

* feat: add reject transfer functions

* chore: trigger rebuild after rebase

* chore: trigger rebuild after rebase

* feat: token registry return functions

* feat: add mint function

* fix: update fixes

* fix: update tests

* revert: revert changes

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>

* feat: owner of function (#79)

* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* fix: update imports

* fix: update imports

* chore(release): 1.6.0-alpha.2 [skip ci]

## [1.6.0-alpha.2](v1.6.0-alpha.1...v1.6.0-alpha.2) (2025-07-15)

### Features

* mint function ([#78](#78)) ([2ea52ce](2ea52ce)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#72](#72)
* owner of function ([#79](#79)) ([81d0e36](81d0e36))

* chore: e2e transfers tests (#82)

* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* chore: add e2e test for transfer functions

* chore: add e2e test for transfer functions

* feat: add ownerOf function

* feat: add test cases

* fix: update test cases for ownerof function

* chore: add e2e test for transfer functions

* chore: add e2e test for transfer functions

* fix: update mock tests

* fix: update mock test fixtures

* fix: update mock tests for mint and return

* fix: update test script

* fix: update imports

* fix: update gitignore

* fix: delete cache

* fix: update imports

* chore: e2e tests reject transfer (#83)

* chore: e2e tests for reject functions

* fix: reject function ethers v6 compatible

* fix: update imports

* fix: mock test cases

* fix: import fixed

* fix: e2e return token tests (#84)

* chore: e2e tests for reject functions

* fix: reject function ethers v6 compatible

* fix: update imports

* fix: mock test cases

* fix: static call fixes

* chore: add e2e test cases

* fix: update imports

* fix: update imports

* fix: tests

* fix: mock functions

* fix: change name

* fix: update imports

* fix: update src imports

* chore(release): 1.6.0-alpha.3 [skip ci]

## [1.6.0-alpha.3](v1.6.0-alpha.2...v1.6.0-alpha.3) (2025-07-18)

### Bug Fixes

* e2e return token tests ([#84](#84)) ([703be01](703be01))

### Miscellaneous Chores

* e2e tests reject transfer ([#83](#83)) ([58a8da2](58a8da2))
* e2e transfers tests ([#82](#82)) ([145e763](145e763))

* chore: merge main into v1  (#85)

* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

## [1.5.4](v1.5.3...v1.5.4) (2025-06-17)

### Bug Fixes

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

## [1.5.5](v1.5.4...v1.5.5) (2025-06-18)

### Bug Fixes

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: support passing titleEscrowAddress to fetchEndorsementChain (#80)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0 [skip ci]

## [1.6.0](v1.5.5...v1.6.0) (2025-07-14)

### Features

* support passing titleEscrowAddress to fetchEndorsementChain ([#80](#80)) ([aa7b4f0](aa7b4f0))

* feat: add astron v5 (#81)

Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* chore(release): 1.7.0 [skip ci]

## [1.7.0](v1.6.0...v1.7.0) (2025-07-15)

### Features

* add astron v5 ([#81](#81)) ([0bebeae](0bebeae))

---------

Co-authored-by: RishabhS7 <59636880+RishabhS7@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
Co-authored-by: caict-develop-zhangbo <68949988+caict-develop-zhangbo@users.noreply.github.com>
Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* fix: trigger release (#86)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0-alpha.4 [skip ci]

## [1.6.0-alpha.4](v1.6.0-alpha.3...v1.6.0-alpha.4) (2025-07-23)

### Bug Fixes

* trigger release ([#86](#86)) ([d2fb6fb](d2fb6fb))

### Miscellaneous Chores

* merge main into v1  ([#85](#85)) ([b81b422](b81b422)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#80](#80) [#80](#80) [#81](#81) [#81](#81)

* chore: rebase v1 with main (#95)

* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* feat: support passing titleEscrowAddress to fetchEndorsementChain (#80)

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>

* chore(release): 1.6.0 [skip ci]

* support passing titleEscrowAddress to fetchEndorsementChain ([#80](#80)) ([aa7b4f0](aa7b4f0))

* feat: add astron v5 (#81)

Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* chore(release): 1.7.0 [skip ci]

* add astron v5 ([#81](#81)) ([0bebeae](0bebeae))

* fix: update tradetrust-tt/tradetrust package (#87)

* fix: update tradetrust-tt/tradetrust package

* fix: update version

* fix: update imports

* chore(release): 1.7.1 [skip ci]

* update tradetrust-tt/tradetrust package ([#87](#87)) ([e4f75a4](e4f75a4))

* fix: upgrade packages (#88)

* chore(release): 1.7.2 [skip ci]

* upgrade packages ([#88](#88)) ([0cc314e](0cc314e))

* fix: error message types (#89)

* chore(release): 1.7.3 [skip ci]

* error message types ([#89](#89)) ([d83bada](d83bada))

* fix: upgrade packages (#90)

* chore(release): 1.7.4 [skip ci]

* upgrade packages ([#90](#90)) ([758651d](758651d))

---------

Co-authored-by: RishabhS7 <59636880+RishabhS7@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
Co-authored-by: caict-develop-zhangbo <68949988+caict-develop-zhangbo@users.noreply.github.com>
Co-authored-by: maxufeng <maxufeng@caict.ac.cn>

* fix: add w3c credential status check (#72)

* fix: add w3c credential status check

* fix: update test

* fix: update enum status codes

* fix: remove console

* chore(release): 1.5.4 [skip ci]

* add w3c credential status check ([#72](#72)) ([0111cb3](0111cb3))

* fix: upgrade package (#73)

* chore(release): 1.5.5 [skip ci]

* upgrade package ([#73](#73)) ([3c6c9c7](3c6c9c7))

* fix: update edsa w3c verifier

* fix: resolve conflicts

* fix: rebase

* fix: resolve conflicts

* fix: update package lock

* fix: resolve conflicts

* fix: verify test

* fix: cryptosuit types

---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Ng Han Inn <43451336+nghaninn@users.noreply.github.com>
Co-authored-by: Moiz Shaikh <58319530+Moiz47@users.noreply.github.com>
Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
Co-authored-by: caict-develop-zhangbo <68949988+caict-develop-zhangbo@users.noreply.github.com>
Co-authored-by: maxufeng <maxufeng@caict.ac.cn>
Co-authored-by: rongquan1 <rongquan.low@gmail.com>
* fix: add w3c version detection function

* fix: add w3c version detection function

* fix: update packages

* fix: version bump w3c
## [1.6.0-alpha.5](v1.6.0-alpha.4...v1.6.0-alpha.5) (2025-08-19)

### Bug Fixes

* add w3c version detection function ([#103](#103)) ([3270cc6](3270cc6))

### Miscellaneous Chores

* ecdsa w3c verify ([#100](#100)) ([484e1ff](484e1ff)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#80](#80) [#80](#80) [#81](#81) [#81](#81) [#87](#87) [#87](#87) [#88](#88) [#88](#88) [#89](#89) [#89](#89) [#90](#90) [#90](#90) [#96](#96) [#96](#96) [#97](#97) [#97](#97) [#74](#74) [#74](#74) [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#78](#78) [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#72](#72)
* rebase v1 with main ([#95](#95)) ([b54b146](b54b146)), closes [#72](#72) [#72](#72) [#73](#73) [#73](#73) [#80](#80) [#80](#80) [#81](#81) [#81](#81) [#87](#87) [#87](#87) [#88](#88) [#88](#88) [#89](#89) [#89](#89) [#90](#90) [#90](#90)
* feat: update sign and derive method

* feat: test case update

* feat: sign and derive update

---------

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
## [1.6.0-alpha.6](v1.6.0-alpha.5...v1.6.0-alpha.6) (2025-08-20)

### Features

* update sign and derive method ([#101](#101)) ([7b8a012](7b8a012))
* feat: update document builder to data model 2.0

* feat: document builder readme update

* feat: document builder update

* feat: document builder minor updates

* feat: mock OA document status verify

---------

Co-authored-by: moiz-sgtradex <moiz.shaikh@sgtradextech.com>
## [1.6.0-alpha.7](v1.6.0-alpha.6...v1.6.0-alpha.7) (2025-08-22)

### Features

* update document builder to data model 2.0 ([#104](#104)) ([f04f153](f04f153))
Merge remote-tracking branch 'origin/v1' into release/v1-merge
@coderabbitai

coderabbitai Bot commented Aug 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Introduces W3C VC Data Model 2.0 support, multikey inputs, selective disclosure signing/deriving (ECDSA-SD-2023, BBS+), new deriveW3C API, updated DocumentBuilder (sign/derive/verify/context handling), adds an ECDSA integrity verifier, extends utils for obfuscation detection, updates tests/fixtures, README, and package dependencies.

Changes

Cohort / File(s) Summary
Documentation
README.md
Reorganized sections; updated examples to VC DM v2.0, multikey, DataIntegrityProof; added deriveW3C and selective disclosure usage; expanded encrypt API notes.
Package manifest
package.json
Bumped @trustvc/w3c* deps to 1.3.0-alpha.x; added @trustvc/w3c meta package.
Core Builder
src/core/documentBuilder.ts
Added derive(revealedAttributes); updated sign(privateKey, cryptoSuite?: CryptoSuiteName, options?); enforced VC v2 contexts; switched issuance/expiration to validFrom/validUntil; adjusted verification requiring derive for ECDSA-SD-2023; new context URLs.
W3C APIs
src/w3c/sign.ts, src/w3c/derive.ts, src/w3c/index.ts
signW3C now uses CryptoSuiteName (default 'ecdsa-sd-2023') and options { mandatoryPointers? }; added deriveW3C wrapper; re-exported derive.
Verification fragments
src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts, src/verify/fragments/document-integrity/w3cSignatureIntegrity.ts, src/verify/fragments/issuer-identity/w3cIssuerIdentity.ts, src/verify/fragments/document-status/w3cCredentialStatus.ts, src/verify/fragments/index.ts, src/verify/verify.ts
New ECDSA DataIntegrityProof verifier with derive-on-demand; import source adjustments to @trustvc/w3c-vc; exported new fragment; included in verifier list.
Tests — Core
src/__tests__/core/documentBuilder.test.ts, src/__tests__/core/verify.test.ts
Added VC v2.0 ECDSA/BBS flows, derive-before-verify paths, new contexts/fields, fixtures, and parameterized ECDSA verification tests.
Tests — W3C flows
src/__tests__/w3c/sign.test.ts, src/__tests__/w3c/derive.test.ts
Updated sign tests for explicit cryptoSuite and options; added derive tests for selective disclosure pointers.
Fixtures
src/__tests__/fixtures/fixtures.ts
Added ECDSA W3C VC v2.0/v1.1 and derived fixtures; frozen objects; updated contexts, subject, status, proofs.
OpenAttestation utils change
src/open-attestation/utils.ts
Removed isObfuscated export/import from this module.
Documents utils additions
src/utils/documents/index.ts
Added isObfuscated and getObfuscatedData helpers supporting OA v2/v3 and signed VC; extended public API.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant Builder as DocumentBuilder
  participant W3C as signW3C
  participant VC as @trustvc/w3c-vc

  App->>Builder: build() with VC v2.0 context
  App->>Builder: sign(privateKey, "ecdsa-sd-2023", {mandatoryPointers})
  Builder->>W3C: signW3C(credential, key, "ecdsa-sd-2023", {mandatoryPointers})
  W3C->>VC: signCredential(..., cryptoSuite, options)
  VC-->>W3C: Signed VC (DataIntegrityProof)
  W3C-->>Builder: Signed VC
  Builder-->>App: Signed VC
Loading
sequenceDiagram
  autonumber
  actor App
  participant Builder as DocumentBuilder
  participant Derive as deriveW3C
  participant VC as @trustvc/w3c-vc

  App->>Builder: derive(revealedAttributes)
  Builder->>Derive: deriveW3C(signedVC, revealedAttributes)
  Derive->>VC: deriveCredential(signedVC, revealedAttributes)
  VC-->>Derive: { derived }
  Derive-->>Builder: Derived VC
  Builder-->>App: Derived VC (isDerived = true)
Loading
sequenceDiagram
  autonumber
  actor Verifier
  participant Verify as verify()
  participant Frag1 as w3cSignatureIntegrity
  participant Frag2 as ecdsaW3CSignatureIntegrity
  participant VC as @trustvc/w3c-vc

  Verifier->>Verify: verify(document)
  Verify->>Frag1: test/verify(document)
  Frag1-->>Verify: SKIPPED or result
  Verify->>Frag2: test(document)
  alt DataIntegrityProof ecdsa-sd-2023
    Frag2->>VC: verifyW3CSignature(document)
    alt Needs derivation
      Frag2->>VC: deriveCredential(document, [])
      Frag2->>VC: verifyW3CSignature(derived)
      Frag2-->>Verify: VALID ("after derivation")
    else OK
      Frag2-->>Verify: VALID
    end
  else Not applicable
    Frag2-->>Verify: SKIPPED
  end
  Verify-->>Verifier: Aggregated result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

released on @v1

Suggested reviewers

  • RishabhS7

Poem

In verdant fields of VC two-point-oh, I hop,
Keys now multibase, with cryptosuites on top.
I nibble secrets, disclose just a few,
Derive, verify—ECDSA-SD, woo-hoo!
Proofs in my paw, I stamp and I go—
Thump-thump! Trust blooms where credentials grow. 🥕

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch release/v1-merge

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
6.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
src/verify/fragments/issuer-identity/w3cIssuerIdentity.ts (2)

46-61: Handle VC 2.0 issuer object and multiple proofs

VC 2.0 allows issuer to be a string or object ({ id }), and proof can be a single object or an array. The current check assumes a string issuer and a single proof, which may incorrectly mark valid credentials as INVALID.

Apply this diff to robustly support both forms:

-    const doc = document as SignedVerifiableCredential;
-    if (doc.proof?.verificationMethod?.split('#')[0] !== doc.issuer) {
+    const doc = document as SignedVerifiableCredential;
+    const issuerId =
+      typeof doc.issuer === 'string' ? doc.issuer : (doc.issuer as { id?: string })?.id;
+    const proofs = (Array.isArray(doc.proof) ? doc.proof : [doc.proof]).filter(Boolean);
+    const vmIssuers = proofs
+      .map((p) => p?.verificationMethod?.split('#')[0])
+      .filter(Boolean) as string[];
+    const issuerMatchesVM = issuerId && vmIssuers.some((vm) => vm === issuerId);
+    if (!issuerId || !issuerMatchesVM) {
       return {
         type: 'ISSUER_IDENTITY',
         name: 'W3CIssuerIdentity',
         data: false,
         reason: {
-          message: `Issuer and verification method do not match.`,
+          message: `Issuer and verificationMethod do not match or are missing.`,
         },
         status: 'INVALID',
       };
     }

6-25: Broaden DID resolution beyond did:web (without breaking existing behavior)

checkDidWebResolve only resolves via well-known did:web when no documentLoader is provided. For other DID methods, this will always return false. At minimum, we should attempt resolution via documentLoader (when provided) for any DID and only fall back to queryDidDocument for did:web.

Apply this contained update:

-const checkDidWebResolve = async (
+const checkDidWebResolve = async (
   did: string,
   documentLoader?: DocumentLoader,
 ): Promise<boolean> => {
   try {
-    if (documentLoader) {
-      return !!(await documentLoader(did)).document;
-    }
-
-    const { wellKnownDid } = await queryDidDocument({ did });
-
-    if (!wellKnownDid) {
-      throw new Error(`Failed to resolve DID: ${did}`);
-    }
-
-    return true;
+    // Prefer user-supplied loader for any DID method
+    if (documentLoader) {
+      const res = await documentLoader(did);
+      return !!res?.document;
+    }
+    // Fallback: only did:web is supported via queryDidDocument
+    if (did?.startsWith('did:web:')) {
+      const { wellKnownDid } = await queryDidDocument({ did });
+      if (!wellKnownDid) throw new Error(`Failed to resolve DID: ${did}`);
+      return true;
+    }
+    // Unknown DID methods without documentLoader cannot be resolved here
+    return false;
   } catch {
     return false;
   }
 };
src/utils/documents/index.ts (1)

55-69: Return type mismatch and possible undefined in getTokenId

getTokenId is declared to return string, but it can return undefined when tokenId is absent. This discrepancy can leak undefined downstream.

Apply this fix to make the return type explicit and the intent clear:

-export const getTokenId = (
-  document: WrappedOrSignedOpenAttestationDocument | SignedVerifiableCredential,
-): string => {
+export const getTokenId = (
+  document: WrappedOrSignedOpenAttestationDocument | SignedVerifiableCredential,
+): string | undefined => {
...
-  return tokenId && `0x${tokenId}`;
+  return tokenId ? `0x${tokenId}` : undefined;
README.md (5)

117-119: Fix inconsistency: intro still says “using BBS+ signatures” while default is now ECDSA-SD-2023.

The paragraph at Lines 117–119 conflicts with the default described at Lines 158–159. Update the intro to reflect ECDSA-SD-2023 as the default and that BBS+ is an alternative.

Apply:

- > The TrustVC Signing feature simplifies the signing process for OA documents and W3C-compliant verifiable credentials using BBS+ signatures. This feature allows you to easily sign W3C Verifiable Credentials (VCs) and ensure they comply with the latest standards.
+ > The TrustVC Signing feature simplifies the signing process for OA documents and W3C-compliant verifiable credentials. By default, it uses the ECDSA-SD-2023 crypto suite (Data Integrity), with BBS+ available as an alternative.

Also applies to: 158-159


127-154: Correct OA wrapping API name in example (wrapOADocument vs wrapOA).

Elsewhere the API is documented as wrapOADocument/wrapOADocuments. Using wrapOA here will confuse users.

Apply:

-import { wrapOA, signOA } from '@trustvc/trustvc';
+import { wrapOADocument, signOA } from '@trustvc/trustvc';
@@
-const wrappedDocument = await wrapOA(rawDocument);
+const wrappedDocument = await wrapOADocument(rawDocument);

406-427: Decryption API should not generate a new nonce; require the encryption nonce.

Generating a new nonce on decrypt will always fail. Either:

  • make nonce required in the signature; or
  • document how the nonce is transported (e.g., prefixed to ciphertext) and parse it internally.

Current text is misleading and unsafe.

Apply:

-```ts
-function decrypt(encryptedMessage: string, key: string, nonce?: string): string;
-```
+```ts
+function decrypt(encryptedMessage: string, key: string, nonce: string): string;
+```
@@
-- `nonce` (string, optional): A 12-byte nonce used during encryption. If omitted, one will be generated.
+- `nonce` (string): The 12-byte nonce used during encryption. It must match the encryption nonce.
@@
-2. If a custom nonce is not provided, the function will generate a new one, which may not match the original encryption nonce and will result in decryption failure.
+2. The same nonce used during encryption must be supplied; otherwise decryption will fail.

If your implementation already embeds the nonce into the ciphertext, I can adjust the docs instead to reflect “nonce is parsed from ciphertext” and keep the signature optional.


658-676: Token Registry v5 function names: mismatch between text and code sample.

Text mentions rejectTransferBeneficiary and rejectTransferOwners; the first code block shows rejectTransferOwner (singular). Align names to the actual contract ABI to avoid confusion.

I can fix the section once you confirm the exact method names in the v5 ABI.


739-744: Clarify that expirationDate() maps to the validUntil property

To avoid confusion between the method name and the emitted JSON field, please update the README example to explicitly state that calling builder.expirationDate() sets the validUntil property in the output.

• File: README.md
• Lines: ~739–744

Suggested diff:

 You can set a valid until date (expiration) for the document.

 ```ts
 builder.expirationDate('2026-01-01T00:00:00Z');

+> Note: the expirationDate() method populates the validUntil field in the resulting JSON (per W3C Verifiable Credentials Data Model 2.0).


</blockquote></details>
<details>
<summary>src/__tests__/core/documentBuilder.test.ts (1)</summary><blockquote>

`6-22`: **Isolate test-only private keys and allowlist in Gitleaks**

Gitleaks is flagging embedded `privateKeyBase58` and `secretKeyMultibase` values in your test suite—specifically in:
- `src/__tests__/core/documentBuilder.test.ts`
- `src/__tests__/w3c/sign.test.ts`

These hardcoded secrets will break your CI pipelines whenever Gitleaks runs. To resolve this:

• Move all test key pairs into a dedicated fixtures file (e.g., `src/__tests__/fixtures/keys.ts`) and update both tests to import from there.  
• In your `gitleaks.toml`, add an allowlist entry scoped to this fixtures file and the exact Base58/Multibase patterns you’re using.  
• As an alternative for stricter policy, load these values from environment variables at test runtime instead of committing them, ensuring zero secrets in the repo.

If helpful, I can draft:
1. A sample `src/__tests__/fixtures/keys.ts` exporting these two `PrivateKeyPair` objects.  
2. A `gitleaks.toml` snippet showing how to allowlist patterns only in that file.  

Let me know if you’d like those examples!

</blockquote></details>
<details>
<summary>src/core/documentBuilder.ts (1)</summary><blockquote>

`110-114`: **Fix credentialSubject() parameter type**

credentialSubject currently accepts Partial<VerifiableCredential>, which is misleading and overly permissive. It should accept a credentialSubject payload, e.g., Record<string, unknown> (or a dedicated CredentialSubject type if exported).


```diff
-  credentialSubject(subject: Partial<VerifiableCredential>) {
+  credentialSubject(subject: Record<string, unknown>) {
     if (this.isSigned) throw new Error('Configuration Error: Document is already signed.');
     this.document.credentialSubject = subject;
     return this;
   }
🧹 Nitpick comments (27)
src/verify/fragments/document-status/w3cCredentialStatus.ts (1)

47-55: Minor: tighten the type guard for credentialStatus entries

The test accepts only 'BitstringStatusListEntry' and 'StatusList2021Entry'. If additional entry types are added later (e.g., aliases), this will silently skip verification. Consider centralizing the supported types behind a helper/type-guard to reduce stringly-typed checks.

Apply this small refactor:

-    const test = (credentialStatus: CredentialStatus) =>
-      ['BitstringStatusListEntry', 'StatusList2021Entry'].includes(credentialStatus?.type);
+    const isSupportedStatusEntry = (cs: CredentialStatus) =>
+      cs?.type === 'BitstringStatusListEntry' || cs?.type === 'StatusList2021Entry';
...
-    if (isSignedDocument(document) && credentialStatuses.every(test)) {
+    if (isSignedDocument(document) && credentialStatuses.every(isSupportedStatusEntry)) {
       return true;
src/utils/documents/index.ts (1)

128-140: Scope decision for getObfuscatedData

Limiting getObfuscatedData to wrapped OA v2/v3 is fine for now. If we decide to surface SD metadata for W3C derived credentials later (e.g., ECDSA-SD disclosures), we can introduce a separate helper to avoid overloading this function’s semantics.

README.md (2)

184-186: Add trailing comma after validUntil for valid TS object literal.

Apply:

-  validFrom: '2024-04-01T12:19:52Z',
-  validUntil: '2029-12-03T12:19:52Z'
+  validFrom: '2024-04-01T12:19:52Z',
+  validUntil: '2029-12-03T12:19:52Z',

284-325: Add an ECDSA-SD v2 verification example (derive-then-verify).

This section currently shows a BBS v1.1 VC. Given v2/ECDSA is now the default, add an example that:

  • derives a credential with ecdsa-sd-2023, then
  • calls verifyDocument on the derived credential.

This reduces friction for the primary path.

I can add a concise example alongside the BBS sample. Want me to push a README patch?

src/verify/fragments/index.ts (1)

34-35: Ordering/consistency: export order mirrors imports.

Optional: keep alphabetical order or group integrity verifiers together for readability in the barrel file.

src/verify/fragments/document-integrity/w3cSignatureIntegrity.ts (2)

11-15: Skip message mentions only BbsBlsSignature2020 but test() accepts BbsBlsSignatureProof2020 too.

Adjust message for accuracy.

Apply:

-        message: `Document either has no proof or proof.type is not 'BbsBlsSignature2020'.`,
+        message: `Document either has no proof or proof.type is not 'BbsBlsSignature2020' or 'BbsBlsSignatureProof2020'.`,

2-3: Use absolute/barrel import for verifyW3CSignature to reduce relative path depth

  • In src/verify/fragments/document-integrity/w3cSignatureIntegrity.ts (lines 2–3), you’re currently importing:
    import { verifyW3CSignature } from '../../../w3c/verify';
  • Your tsconfig.json defines
    "baseUrl": ".",
    "paths": {
      "src/*": ["./src/*"]
    }
    so you can import using the alias:
    import { verifyW3CSignature } from 'src/w3c/verify';
  • Even better, src/w3c/index.ts barrels exports from ./verify, allowing:
    import { verifyW3CSignature } from 'src/w3c';
  • Switching to an absolute or barrel import will make your codebase more maintainable by avoiding brittle relative-depth churn.
src/verify/verify.ts (1)

66-73: W3C verifiers order: ECDSA verifier inclusion looks correct; consider placing ECDSA before BBS or vice versa based on typical traffic.

If most v2 traffic is ECDSA-SD, consider ordering ecdsaW3CSignatureIntegrity before w3cSignatureIntegrity to short-circuit earlier. Minor.

Apply (optional):

-const w3cVerifiers: Verifier<VerificationFragment>[] = [
-  w3cSignatureIntegrity,
-  ecdsaW3CSignatureIntegrity,
+const w3cVerifiers: Verifier<VerificationFragment>[] = [
+  ecdsaW3CSignatureIntegrity,
+  w3cSignatureIntegrity,
   w3cCredentialStatus,
   credentialStatusTransferableRecordVerifier,
   w3cEmptyCredentialStatus,
   w3cIssuerIdentity,
 ];
src/__tests__/w3c/derive.test.ts (2)

20-31: Fix test description to match behavior (“with custom selective pointers”).

The second test passes ['/renderMethod', '/qrCode'] but the description says “without custom selective pointers”.

Apply this diff to clarify intent:

-  it('should derive a W3C v2.0 document using ECDSA-SD-2023 without custom selective pointers', async () => {
+  it('should derive a W3C v2.0 document using ECDSA-SD-2023 with custom selective pointers', async () => {

6-18: Optional: parameterize the two ECDSA-SD derivation tests.

Both tests are identical except for the selective pointers. Consider table-driven tests to reduce duplication and ease future additions.

Example structure:

+  const cases = [
+    { name: 'without selective pointers', pointers: [], hasRender: false, hasQr: false },
+    { name: 'with selective pointers', pointers: ['/renderMethod', '/qrCode'], hasRender: true, hasQr: true },
+  ];
+
-  it('should derive a W3C v2.0 document using ECDSA-SD-2023 without custom selective pointers', async () => {
-    const result = await deriveW3C(
-      ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 as SignedVerifiableCredential,
-      [],
-    );
-    ...
-  });
+  cases.forEach(({ name, pointers, hasRender, hasQr }) =>
+    it(`should derive a W3C v2.0 document using ECDSA-SD-2023 ${name}`, async () => {
+      const result = await deriveW3C(
+        ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 as SignedVerifiableCredential,
+        pointers,
+      );
+      expect(!!result.derived.renderMethod).toBe(hasRender);
+      expect(!!result.derived.qrCode).toBe(hasQr);
+    }),
+  );
src/w3c/derive.ts (2)

8-13: Tighten JSDoc types to mirror the TypeScript signature.

JSDoc currently uses “object” and “object|string[]”, which is looser than the TS types. Align them for better editor/help and consistency.

- * @param {object} credential - The verifiable credential to be selectively disclosed.
- * @param {object|string[]} revealedAttributes - For BBS+: The attributes from the credential that should be revealed. For ECDSA-SD-2023: Array of selective pointers.
- * @returns {Promise<DerivedResult>} A DerivedResult containing the derived proof or an error message.
+ * @param {SignedVerifiableCredential} credential - The verifiable credential to be selectively disclosed.
+ * @param {ContextDocument|string[]} revealedAttributes - For BBS+: schema-based attributes to reveal. For ECDSA-SD-2023: array of selective pointers.
+ * @returns {Promise<DerivedResult>} Derived proof and derived credential details, or an error.

15-20: Consider future-proofing deriveW3C with an options passthrough.

If deriveCredential starts supporting options (e.g., a custom documentLoader), you may want deriveW3C to accept and pass them through. Not a blocker—flagging for API evolution awareness.

Would you like me to check the latest @trustvc/w3c-vc deriveCredential signature to confirm whether an options parameter is already supported?

src/__tests__/fixtures/fixtures.ts (2)

1354-1419: Remove large commented-out fixture to reduce noise and avoid drift.

This entire commented block duplicates an older ECDSA v2.0 fixture. Rely on git history instead of keeping dead code in-tree.

-// export const ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 = freezeObject({
-//   '@context': [
-//     ...
-// });

1433-1436: Normalize tokenNetwork.chainId to a number for consistency.

Elsewhere (e.g., W3C_TRANSFERABLE_RECORD) chainId is numeric (80002). Here it’s a string ('80001'). Unifying on number avoids downstream parsing ambiguity.

-    tokenNetwork: { chain: 'MATIC', chainId: '80001' },
+    tokenNetwork: { chain: 'MATIC', chainId: 80001 },
src/__tests__/w3c/sign.test.ts (3)

7-11: Strengthen TestCase typing and naming to reflect the public API.

  • proofType actually maps to the cryptoSuite param; rename for clarity.
  • options should use the concrete type shape used by signW3C (mandatoryPointers?: string[]).
-interface TestCase {
-  name: string;
-  proofType: CryptoSuiteName | undefined;
-  options: Record<string, unknown> | undefined;
-}
+interface TestCase {
+  name: string;
+  cryptoSuite?: CryptoSuiteName;
+  options?: { mandatoryPointers?: string[] };
+}

And update the usages accordingly:

-  ecdsaSdTestCases.forEach(({ name, proofType, options }) => {
+  ecdsaSdTestCases.forEach(({ name, cryptoSuite, options }) => {
...
-      proofType,
+      cryptoSuite,

18-29: Avoid committing private keys directly in tests; source them from env with safe defaults.

Directly embedding privateKeyBase58 is commonly flagged by secret scanners and can normalize risky patterns. Prefer env overrides in CI/local runs.

Apply this diff to make the BLS key configurable (keeps current key as explicit test default):

-    const signingResult = await signW3C(
-      documentWithoutProof,
-      {
-        id: 'did:web:trustvc.github.io:did:1#keys-1',
-        controller: 'did:web:trustvc.github.io:did:1',
-        type: VerificationType.Bls12381G2Key2020,
-        publicKeyBase58:
-          'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
-        privateKeyBase58: '4LDU56PUhA9ZEutnR1qCWQnUhtLtpLu2EHSq4h1o7vtF',
-      },
+    const signingResult = await signW3C(
+      documentWithoutProof,
+      {
+        id: 'did:web:trustvc.github.io:did:1#keys-1',
+        controller: 'did:web:trustvc.github.io:did:1',
+        type: VerificationType.Bls12381G2Key2020,
+        publicKeyBase58:
+          process.env.TEST_BLS_PUBLIC_BASE58 ??
+          'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
+        privateKeyBase58:
+          process.env.TEST_BLS_PRIVATE_BASE58 ?? '4LDU56PUhA9ZEutnR1qCWQnUhtLtpLu2EHSq4h1o7vtF',
+      },

You can mirror this approach for the Multikey secret below.


62-74: Same note for Multikey: don’t hardcode secretKeyMultibase.

Source from env with a test default, to avoid normalizing secret literals in-repo.

-          publicKeyMultibase: 'zDnaemDNwi4G5eTzGfRooFFu5Kns3be6yfyVNtiaMhWkZbwtc',
-          secretKeyMultibase: 'z42tmUXTVn3n9BihE6NhdMpvVBTnFTgmb6fw18o5Ud6puhRW',
+          publicKeyMultibase:
+            process.env.TEST_ECDSA_PUB_MULTIBASE ??
+            'zDnaemDNwi4G5eTzGfRooFFu5Kns3be6yfyVNtiaMhWkZbwtc',
+          secretKeyMultibase:
+            process.env.TEST_ECDSA_SECRET_MULTIBASE ??
+            'z42tmUXTVn3n9BihE6NhdMpvVBTnFTgmb6fw18o5Ud6puhRW',
src/__tests__/core/verify.test.ts (2)

279-339: Snapshot size is brittle; assert on fragments of interest instead.

The inline snapshot captures many unrelated fragment fields and may change for benign reasons. Prefer focused assertions (arrayContaining/objectContaining) as done elsewhere in this file to reduce flakiness.


1-18: Nit: providerUrl should be documented per-network and overridable.

Hardcoding RPC endpoints is fine for tests, but allow override via env to run in CI without external dependency or to switch endpoints when providers change.

-const providerUrl = 'https://rpc-amoy.polygon.technology';
+const providerUrl = process.env.TEST_RPC_PROVIDER_URL ?? 'https://rpc-amoy.polygon.technology';
src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts (4)

28-31: Use declared constants in test() for consistency

Use PROOF_TYPE and CRYPTOSUITE instead of string literals to keep checks in sync if constants change.

-    return doc.proof?.type === 'DataIntegrityProof' && doc.proof?.cryptosuite === 'ecdsa-sd-2023';
+    return doc.proof?.type === PROOF_TYPE && doc.proof?.cryptosuite === CRYPTOSUITE;

54-56: Consider a safer default reveal set for derivation

Deriving with an empty list ([]) may produce a minimal document that some verifiers reject. Consider revealing a minimal, non-sensitive frame (e.g., @context, type, issuer, validFrom) or accept a reveal from verifierOptions when provided. If you want, I can wire a minimal ContextDocument reveal and plumb an optional reveal into VerifierOptions.


3-4: Prefer importing from the w3c index barrel for consistency

Elsewhere (e.g., DocumentBuilder) imports come from the w3c index. Aligning imports makes refactors easier.

-import { verifyW3CSignature } from '../../../w3c/verify';
+import { verifyW3CSignature } from '../../../w3c';

10-12: Tighten the type guard

Optionally assert that proof has type and cryptosuite fields. It reduces unsafe casts downstream (even though test() already guards typical use).

 function isSignedVerifiableCredential(document: unknown): document is SignedVerifiableCredential {
-  return typeof document === 'object' && document !== null && 'proof' in document;
+  return (
+    typeof document === 'object' &&
+    document !== null &&
+    'proof' in document &&
+    typeof (document as any).proof === 'object' &&
+    (document as any).proof?.type &&
+    (document as any).proof?.cryptosuite
+  );
 }
src/core/documentBuilder.ts (4)

73-76: Rename qrCode type to PascalCase (QRCode) for consistency with RenderMethod

Interface names are PascalCase elsewhere (RenderMethod). Renaming improves consistency without functional change.

-export interface qrCode {
+export interface QRCode {
   uri: string;
   type: string;
 }
@@
-  qrCode(method: qrCode) {
+  qrCode(method: QRCode) {
     if (this.isSigned) throw new Error('Configuration Error: Document is already signed.');
     this.document.qrCode = method;
     this.addContext(QRCODE_CONTEXT_URL); // Add qrcode context to document.
     return this;
   }

Also applies to: 168-174


82-85: Avoid duplicating SignOptions shape across layers

SignOptions is also defined (inline) in src/w3c/sign.ts. Export a single SignOptions type from w3c (or a shared types module) and import it here to prevent drift.

I can consolidate the type into src/w3c/types.ts and update both call sites.

Also applies to: 207-208


305-336: Network-dependent sign() checks: consider dependency injection for testability

verifyTokenRegistry reaches live RPC endpoints and contracts. For unit tests, consider injecting a provider abstraction or allowing a mock to bypass network calls, so tests are deterministic and faster.


92-93: Clean up unused documentType from DocumentBuilder

The documentType field and its constructor parameter are never referenced beyond initialization and can safely be removed to reduce noise.

• src/core/documentBuilder.ts: delete the line

private documentType: string = 'w3c'; // Default to W3C

(line 92)
• src/core/documentBuilder.ts: remove the documentType parameter from the constructor signature and its assignment

- constructor(input: Partial<VerifiableCredential>, documentType: string = 'w3c') {
+ constructor(input: Partial<VerifiableCredential>) {
    this.document = this.initializeDocument(input);
-   this.documentType = documentType;
    …
  }

(lines 104–107)
• Remove the corresponding JSDoc @param {string} [documentType] (line 102)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between de0f39f and 04ca51b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • README.md (13 hunks)
  • package.json (1 hunks)
  • src/__tests__/core/documentBuilder.test.ts (10 hunks)
  • src/__tests__/core/verify.test.ts (4 hunks)
  • src/__tests__/fixtures/fixtures.ts (1 hunks)
  • src/__tests__/w3c/derive.test.ts (1 hunks)
  • src/__tests__/w3c/sign.test.ts (1 hunks)
  • src/core/documentBuilder.ts (9 hunks)
  • src/open-attestation/utils.ts (0 hunks)
  • src/utils/documents/index.ts (1 hunks)
  • src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts (1 hunks)
  • src/verify/fragments/document-integrity/w3cSignatureIntegrity.ts (1 hunks)
  • src/verify/fragments/document-status/w3cCredentialStatus.ts (1 hunks)
  • src/verify/fragments/index.ts (2 hunks)
  • src/verify/fragments/issuer-identity/w3cIssuerIdentity.ts (1 hunks)
  • src/verify/verify.ts (2 hunks)
  • src/w3c/derive.ts (1 hunks)
  • src/w3c/index.ts (1 hunks)
  • src/w3c/sign.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • src/open-attestation/utils.ts
🧰 Additional context used
🧬 Code graph analysis (10)
src/__tests__/w3c/derive.test.ts (2)
src/w3c/derive.ts (1)
  • deriveW3C (15-20)
src/__tests__/fixtures/fixtures.ts (1)
  • ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 (1420-1486)
src/utils/documents/index.ts (3)
src/open-attestation/types.ts (2)
  • WrappedDocument (3-3)
  • OpenAttestationDocument (2-2)
src/w3c/types.ts (1)
  • SignedVerifiableCredential (4-4)
src/open-attestation/utils.ts (2)
  • isWrappedV3Document (50-50)
  • isWrappedV2Document (49-49)
src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts (1)
src/w3c/verify.ts (1)
  • verifyW3CSignature (11-17)
src/w3c/derive.ts (1)
src/w3c/types.ts (1)
  • SignedVerifiableCredential (4-4)
src/verify/verify.ts (2)
src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts (1)
  • ecdsaW3CSignatureIntegrity (14-94)
src/verify/fragments/index.ts (1)
  • ecdsaW3CSignatureIntegrity (34-34)
src/__tests__/core/documentBuilder.test.ts (2)
src/w3c/types.ts (1)
  • PrivateKeyPair (7-7)
src/core/documentBuilder.ts (1)
  • DocumentBuilder (90-349)
src/w3c/sign.ts (1)
src/w3c/types.ts (3)
  • RawVerifiableCredential (2-2)
  • PrivateKeyPair (7-7)
  • SigningResult (3-3)
src/__tests__/core/verify.test.ts (3)
src/__tests__/fixtures/fixtures.ts (3)
  • ECDSA_W3C_DERIVED_DOCUMENT_V1_1 (1517-1545)
  • ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 (1420-1486)
  • ECDSA_W3C_DERIVED_DOCUMENT_V2_0 (1488-1515)
src/core/verify.ts (1)
  • verifyDocument (51-81)
src/verify/fragments/index.ts (1)
  • openAttestationDidSignedDocumentStatus (24-24)
src/__tests__/w3c/sign.test.ts (2)
src/__tests__/fixtures/fixtures.ts (2)
  • W3C_VERIFIABLE_DOCUMENT (1285-1317)
  • ECDSA_W3C_VERIFIABLE_DOCUMENT_V2_0 (1420-1486)
src/w3c/sign.ts (1)
  • signW3C (13-23)
src/core/documentBuilder.ts (3)
src/w3c/types.ts (2)
  • PrivateKeyPair (7-7)
  • SignedVerifiableCredential (4-4)
src/w3c/sign.ts (1)
  • signW3C (13-23)
src/w3c/derive.ts (1)
  • deriveW3C (15-20)
🪛 Gitleaks (8.27.2)
src/__tests__/core/documentBuilder.test.ts

21-21: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


128-128: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


164-164: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


178-178: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


297-297: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


304-304: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


309-309: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


321-321: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


366-366: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


369-369: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

src/__tests__/core/verify.test.ts

12-12: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


297-297: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


304-304: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


309-309: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


321-321: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

src/__tests__/fixtures/fixtures.ts

1368-1368: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


1369-1369: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


1435-1435: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


1436-1436: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


1562-1562: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)


1563-1563: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🔇 Additional comments (14)
src/verify/fragments/document-status/w3cCredentialStatus.ts (1)

6-11: Import source consolidation looks correct

Switching SignedVerifiableCredential to the public @trustvc/w3c-vc import keeps the fragment aligned with the rest of the migration and avoids circular/local barrel dependencies.

src/verify/fragments/issuer-identity/w3cIssuerIdentity.ts (1)

4-4: Import alignment LGTM

Using SignedVerifiableCredential from @trustvc/w3c-vc keeps fragments consistent post-migration.

package.json (1)

124-129: No action needed: @trustvc/w3c-issuer is at its latest published alpha (1.3.0-alpha.5)

Verified that the highest available npm version of @trustvc/w3c-issuer is 1.3.0-alpha.5 – there is no alpha.6 or alpha.7 release to align with the other @trustvc/w3c* packages. The post-install dependency graph shows all v1.3.0-alpha.7 packages correctly pulling in issuer@1.3.0-alpha.5, so the mix of alpha versions is intentional and resolves without conflicts.

src/w3c/sign.ts (1)

8-11: Doc updates match the new default and options

JSDoc reflects CryptoSuiteName typing, default 'ecdsa-sd-2023', and optional mandatoryPointers for ECDSA-SD. Looks good.

src/verify/fragments/index.ts (1)

11-11: Expose ECDSA verifier in public surface — looks good.

Re-exporting ecdsaW3CSignatureIntegrity enables consumers to compose custom verifier sets. Keep it.

src/w3c/index.ts (1)

8-8: Derive API re-export approved; consider explicit exports for tree-shaking.

export * is convenient but can make API diffs noisy. If deriveW3C is the only symbol, prefer:
[ suggest_optional_refactor ]
Apply:

-export * from './derive';
+export { deriveW3C } from './derive';
src/verify/verify.ts (1)

34-35: Adding ECDSA verifier import — good incremental change.

No issues spotted.

src/__tests__/fixtures/fixtures.ts (1)

1419-1486: Address secret-detection warnings (Gitleaks) and ensure no real secrets are committed.

Gitleaks flagged multiple lines as “Generic API Key”. While these look like test data (addresses, proofValue blobs), it’s still best to:

  • Confirm no real private/production keys or secrets are present in fixtures.
  • Add an explicit allowlist for benign patterns (e.g., long base64 proofValue, 0x… addresses) scoped to test paths, or annotate with ignore rules as per your gitleaks policy.

I can generate a repo scan script to surface potentially risky literals (privateKey|secretKey etc.) across test sources if helpful.

src/__tests__/core/verify.test.ts (1)

20-271: Avoid running network/IO-heavy tests concurrently.

Several tests may hit networks (StatusList2021 retrieval, RPC for TransferableRecords). Running them inside describe.concurrent increases flakiness and rate-limit risks. Consider serializing suites that reach out to external services or fully mocking IO.

I can prepare a patch to convert specific suites to serial and/or mock RPC calls and HTTP documentLoader fetches. Let me know your preference.

src/__tests__/core/documentBuilder.test.ts (2)

123-151: End-to-end ECDSA v2.0: solid coverage of sign-derive-verify and error paths

The tests clearly capture the required derive-before-verify behavior and v2 contexts. Timeouts are reasonable given network calls.

Also applies to: 153-173, 353-374


246-248: Good: context injection assertions for renderMethod and qrCode

Validating inclusion of render-method-context-v2 and qrcode-context ensures downstream verifiers have required term definitions.

Also applies to: 264-267

src/core/documentBuilder.ts (3)

176-211: Signing flow looks correct; VC 2.0 contexts and suite-specific contexts are applied properly

  • validFrom defaulting to now for VC 2.0 is appropriate.
  • Data Integrity v2 added for ecdsa-sd-2023; BBS v1 for BBS signatures.

213-225: Derive-before-verify enforcement for ECDSA-SD is correct and matches tests

Enforcing derive() for ecdsa-sd-2023 prevents accidental verification of undisclosed credentials.

Also applies to: 231-242


289-295: Strong VC 2.0 default context and v1.1 guard

Adding VC_V2_URL by default and explicitly rejecting VC_V1_URL aligns with the PR goal and prevents mixed-model documents.

Comment thread README.md
Comment on lines +178 to 181
type: ['Person']
givenName: 'TrustVC',
birthDate: '2024-04-01T12:19:52Z',
type: ['PermanentResident', 'Person'],
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix syntax in rawDocument: missing comma after credentialSubject.type.

The sample as-is is invalid TS/JSON.

Apply:

-  credentialSubject: {
-    type: ['Person']
-    givenName: 'TrustVC',
+  credentialSubject: {
+    type: ['Person'],
+    givenName: 'TrustVC',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
type: ['Person']
givenName: 'TrustVC',
birthDate: '2024-04-01T12:19:52Z',
type: ['PermanentResident', 'Person'],
},
credentialSubject: {
type: ['Person'],
givenName: 'TrustVC',
birthDate: '2024-04-01T12:19:52Z',
},
🤖 Prompt for AI Agents
In README.md around lines 178 to 181, the sample rawDocument is invalid because
there's no comma after credentialSubject.type; add a trailing comma after the
line "type: ['Person']" (and verify surrounding punctuation/quotes) so the
object is valid TS/JSON, then run a quick linter/JSON parse to confirm the
snippet parses correctly.

Comment thread README.md
Comment on lines +216 to +226
const signingResultWithBbs = await signW3C(
rawDocument,
{
id: 'did:web:trustvc.github.io:did:1#keys-1',
controller: 'did:web:trustvc.github.io:did:1',
type: VerificationType.Bls12381G2Key2020,
publicKeyBase58: 'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
privateKeyBase58: '<privateKeyBase58>',
},
'BbsBlsSignature2020'
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

BBS+ example lacks the required security context and still reuses the ECDSA-oriented rawDocument.

For BbsBlsSignature2020, include https://w3id.org/security/bbs/v1 and avoid passing multikey fields. Provide a BBS-specific raw document or override contexts in the call.

Apply:

-const signingResultWithBbs = await signW3C(
-  rawDocument,
+// Use a BBS-specific raw document with the BBS context
+const rawDocumentBbs = {
+  ...rawDocument,
+  '@context': [
+    'https://www.w3.org/ns/credentials/v2',
+    'https://w3id.org/security/bbs/v1',
+    'https://w3id.org/vc/status-list/2021/v1',
+    'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld',
+  ],
+};
+const signingResultWithBbs = await signW3C(
+  rawDocumentBbs,
   {
     id: 'did:web:trustvc.github.io:did:1#keys-1',
     controller: 'did:web:trustvc.github.io:did:1',
     type: VerificationType.Bls12381G2Key2020,
     publicKeyBase58: 'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
     privateKeyBase58: '<privateKeyBase58>',
   },
   'BbsBlsSignature2020'
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const signingResultWithBbs = await signW3C(
rawDocument,
{
id: 'did:web:trustvc.github.io:did:1#keys-1',
controller: 'did:web:trustvc.github.io:did:1',
type: VerificationType.Bls12381G2Key2020,
publicKeyBase58: 'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
privateKeyBase58: '<privateKeyBase58>',
},
'BbsBlsSignature2020'
);
// Use a BBS-specific raw document with the BBS context
const rawDocumentBbs = {
...rawDocument,
'@context': [
'https://www.w3.org/ns/credentials/v2',
'https://w3id.org/security/bbs/v1',
'https://w3id.org/vc/status-list/2021/v1',
'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld',
],
};
const signingResultWithBbs = await signW3C(
rawDocumentBbs,
{
id: 'did:web:trustvc.github.io:did:1#keys-1',
controller: 'did:web:trustvc.github.io:did:1',
type: VerificationType.Bls12381G2Key2020,
publicKeyBase58: 'oRfEeWFresvhRtXCkihZbxyoi2JER7gHTJ5psXhHsdCoU1MttRMi3Yp9b9fpjmKh7bMgfWKLESiK2YovRd8KGzJsGuamoAXfqDDVhckxuc9nmsJ84skCSTijKeU4pfAcxeJ',
privateKeyBase58: '<privateKeyBase58>',
},
'BbsBlsSignature2020'
);
🤖 Prompt for AI Agents
In README.md around lines 216 to 226, the BBS+ example is incorrect: it reuses
an ECDSA-oriented rawDocument and omits the BBS security context. Replace the
rawDocument with a BBS-compatible document (remove multikey fields like
ECDSA-specific publicKey entries) or pass an explicit context override that
includes "https://w3id.org/security/bbs/v1" and any BBS proof-specific contexts,
and update the verification key metadata to the BLS key shape (no ECDSA fields)
before calling signW3C with proof type "BbsBlsSignature2020".

Comment thread README.md
Comment on lines +232 to +279
### 3. **Deriving (Selective Disclosure)**

> When using ECDSA-SD-2023 crypto suite, we can derive a new credential with selective disclosure. This means you can choose which parts of the credential to reveal while keeping others hidden.

```ts
import { deriveW3C } from '@trustvc/trustvc';

// This is a signed document using ecdsa-sd-2023
const signedDocument = {
'@context': [
'https://www.w3.org/ns/credentials/v2',
'https://w3id.org/security/data-integrity/v2',
'https://w3id.org/vc/status-list/2021/v1',
'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld'
],
credentialStatus: {
id: 'https://trustvc.github.io/did/credentials/statuslist/1#1',
type: 'StatusList2021Entry',
statusPurpose: 'revocation',
statusListIndex: '10',
statusListCredential: 'https://trustvc.github.io/did/credentials/statuslist/1'
},
credentialSubject: {
type: ['Person'],
givenName: 'TrustVC',
birthDate: '2024-04-01T12:19:52Z'
},
issuer: 'did:web:trustvc.github.io:did:1',
type: ['VerifiableCredential'],
validFrom: '2024-04-01T12:19:52Z',
validUntil: '2029-12-03T12:19:52Z',
id: 'urn:uuid:0198bd9e-6686-7ccd-9b2a-ce763ae710d7',
proof: {
type: 'DataIntegrityProof',
created: '2025-08-18T14:38:51Z',
verificationMethod: 'did:web:trustvc.github.io:did:1#multikey-1',
cryptosuite: 'ecdsa-sd-2023',
proofPurpose: 'assertionMethod',
proofValue: 'u2V0AhVhAxfLFkbv8J_O3zJAQrSWrEY3sgeMwN02b2eaHEgjnJYu1rnCBYORfZUVZwRoRuNIiY1NTGHmQpzlgqtQz7A0R3FgjgCQDzt3_aUvSMrlIZdsyVcB4KPHHjA4BbSv-PZ4Bbm4GpY5YIA1mQ8LYmpjJ7vNvN3DsfIengZrnziTLO9exbZjn1KqFilhA0lp1y6BZ-fhiUdWsojYesLDSzCy6Tq_AICaIvCjYSJMEaY7SomJnCkdpuhM0GQHDTy5kjzb7sSzowACqDDf9OVhAfOC7vg4WQGrI6M3dvLZW3KlBzp1SurRz1PPeHcqOGEDrqybzIlolwNXMhc2T8rcVLl-E04wNsiVjamvqWAQN-lhA4HmVqIxKuR0QvCMEVq3cjUU7G1pQbgMdp9HZDasOT9nh_k5l3JfcXB1_qtRblljXWN0FRKAr9T-DhxzDzGl3-lhA4nNDzd-6xl74rWqr_7U9XZE7LoE-mbgBsyOAOlfHGumMxwddnEZp2iD2uZ7lLXX8Q-nSDXJVvUqKLksy1l2vqVhAm3daNYjH1kVrTW7V-DElcj3K_QfbHEvjd1F2TGVGtBVhF8o01yCxXRX0vzk-AZLZnpDnAUBTSTF5Q8rF-t7L9lhAO7NeIXQtQsdncqtLm2qk1XzFYL2FM5Hx4GZOX39VyT4T0AlFRZQuY9WXYnvMZSvacRvJaSJk5S3cZ6uBminQgVhAExuTEvJQu42-SiaOJ_6M0EjuQfqIgJE-JHirmYs3AAoH_4EKUtPU3y_jRB8XFZxA-wtFDv3KJjqXtNo5aA_6f1hAaokZPSJghFufTaVR8LAwHpXOncGJblKpUZQjKWuA_o2s6tGmx-ja0wgpsqSxvAGMTtkhFTMOI2-tzUuGE05tk1hAzABtV2yEX-RAQFpxkuV0XydAsJDh2dPscrpPHqMfmORsC3xRNL73uDaqqlaL99CvOgq4kJWmChw7TUYO62yaSVhA5-F-snwj-OZtws7_qMwvBgeNK9wvkZTlFLjRV6GDYx6r5TaLkR05GVzyBMv0Qs2z-cXPRZByS7p7_hbeykoYSYJnL2lzc3VlcmovdmFsaWRGcm9t'
}
};

// Derive a new credential with only specific fields disclosed
const derivationResult = await deriveW3C(signedDocument, {
// Only reveal the credential type and givenName, hide birthDate
selectivePointers: ['/type', '/credentialSubject/givenName']
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Selective disclosure options name alignment (deriveW3C).

Double-check the parameter name “selectivePointers” matches the actual deriveW3C options type exported from src/w3c/derive.ts. If the library expects “revealedAttributes” or “revealPaths”, this example will confuse users.

Run:

If needed, I can patch the README to the correct option name. Do you want me to generate that diff?


🏁 Script executed:

#!/bin/bash
# Confirm deriveW3C options type and property names
rg -nP --type=ts -C2 '\bexport\s+async\s+function\s+deriveW3C\s*\('
rg -nP --type=ts -C3 'interface\s+.*(Derive|Selective).*Options|type\s+.*(Derive|Selective).*Options'

Length of output: 173


🏁 Script executed:

#!/bin/bash
# Search for deriveW3C function definition and its option type in TypeScript files
rg -n --type ts "deriveW3C" -C5
rg -n --type ts "interface.*Options" -C3
rg -n --type ts "type.*Options" -C3

Length of output: 7644


Update README to use the correct deriveW3C parameter

The deriveW3C function (in src/w3c/derive.ts) takes two positional arguments—credential and a revealedAttributes parameter of type ContextDocument | string[]. It does not accept an options object with a selectivePointers field. To selectively disclose ECDSA-SD-2023 fields, pass an array of JSON Pointers directly.

• Location: README.md (around lines 232–279)
• Change the deriveW3C example to pass the pointer array instead of { selectivePointers: […] }

Suggested diff:

- // Derive a new credential with only specific fields disclosed
- const derivationResult = await deriveW3C(signedDocument, {
-   // Only reveal the credential type and givenName, hide birthDate
-   selectivePointers: ['/type', '/credentialSubject/givenName']
- });
+ // Derive a new credential with only specific fields disclosed
+ const derivationResult = await deriveW3C(
+   signedDocument,
+   // Only reveal the credential type and givenName, hide birthDate
+   ['/type', '/credentialSubject/givenName']
+ );

This aligns the example with the actual signature:

export const deriveW3C = async (
  credential: SignedVerifiableCredential,
  revealedAttributes: ContextDocument | string[],
): Promise<DerivedResult> => {  }
🤖 Prompt for AI Agents
README.md around lines 232 to 279: the example calls deriveW3C with an options
object { selectivePointers: [...] } but deriveW3C expects the second positional
argument to be a ContextDocument | string[] of JSON Pointers; update the README
example to call deriveW3C(signedDocument,
['/type','/credentialSubject/givenName']) (i.e. pass the pointer array directly
as the second argument) and remove the options object wrapper so the example
matches the function signature in src/w3c/derive.ts.

Comment thread README.md
Comment on lines +693 to 695
'@context': 'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld'
});
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

DocumentBuilder base @context likely needs VC v2 and Data Integrity contexts.

Using only the citizenship vocab context may yield an invalid VC unless the builder injects defaults. To be explicit and copy-paste friendly, include VC v2 and DI v2 here.

Apply:

-const builder = new DocumentBuilder({
-  '@context': 'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld'
-});
+const builder = new DocumentBuilder({
+  '@context': [
+    'https://www.w3.org/ns/credentials/v2',
+    'https://w3id.org/security/data-integrity/v2',
+    'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld',
+  ],
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'@context': 'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld'
});
```
const builder = new DocumentBuilder({
'@context': [
'https://www.w3.org/ns/credentials/v2',
'https://w3id.org/security/data-integrity/v2',
'https://w3c-ccg.github.io/citizenship-vocab/contexts/citizenship-v2.jsonld',
],
});
🤖 Prompt for AI Agents
In README.md around lines 693 to 695, the DocumentBuilder example sets
'@context' to only the citizenship-v2 JSON-LD context which can produce an
invalid Verifiable Credential; update the example so the base '@context' is an
array that explicitly includes the W3C Verifiable Credentials v2 context and the
Data Integrity v2 context in addition to the citizenship-v2 context (preserve
order with VC v2 first, DI v2 next, then the citizenship vocab) so the snippet
is copy-paste friendly and produces a valid VC.

import { describe, it, expect, beforeEach } from 'vitest';
import { DocumentBuilder } from '../../core/documentBuilder';
import { PrivateKeyPair, VerificationType } from '@trustvc/w3c-issuer';
import { ContextDocument } from '@trustvc/w3c-context';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Import ContextDocument from the VC types package, not the context constants package

ContextDocument is defined in @trustvc/w3c-vc. Importing from @trustvc/w3c-context risks type drift or missing type export.

-import { ContextDocument } from '@trustvc/w3c-context';
+import { ContextDocument } from '@trustvc/w3c-vc';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { ContextDocument } from '@trustvc/w3c-context';
import { ContextDocument } from '@trustvc/w3c-vc';
🤖 Prompt for AI Agents
In src/__tests__/core/documentBuilder.test.ts around line 4 the test imports
ContextDocument from '@trustvc/w3c-context'; this is incorrect — import
ContextDocument from the VC types package '@trustvc/w3c-vc' instead. Replace the
import source so the test uses the official type export from '@trustvc/w3c-vc'
to avoid type drift or missing exports.

Comment on lines 615 to +635
describe.concurrent('V3 verify', () => {
it('should verify a DND_DID document and return fragments', async ({ expect }) => {
vi.spyOn(openAttestationDidSignedDocumentStatus, 'verify').mockResolvedValue({
data: {
details: {
issuance: {
did: 'did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90#controller',
issued: true,
},
revocation: {
revoked: false,
},
},
issuedOnAll: true,
revokedOnAny: false,
},
name: 'OpenAttestationDidSignedDocumentStatus',
status: 'VALID',
type: 'DOCUMENT_STATUS',
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Restore spy/mocks to avoid cross-test leakage.

You stub openAttestationDidSignedDocumentStatus.verify but never restore it. The stub may bleed into subsequent tests and change expectations (e.g., DID_TOKEN_REGISTRY test). Use mockResolvedValueOnce and restore after the test or add an afterEach in this describe.

Apply this diff:

-  it('should verify a DND_DID document and return fragments', async ({ expect }) => {
-    vi.spyOn(openAttestationDidSignedDocumentStatus, 'verify').mockResolvedValue({
+  it('should verify a DND_DID document and return fragments', async ({ expect }) => {
+    vi.spyOn(openAttestationDidSignedDocumentStatus, 'verify').mockResolvedValueOnce({
       data: {
         details: {
           issuance: {
             did: 'did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90#controller',
             issued: true,
           },
           revocation: {
             revoked: false,
           },
         },
         issuedOnAll: true,
         revokedOnAny: false,
       },
       name: 'OpenAttestationDidSignedDocumentStatus',
       status: 'VALID',
       type: 'DOCUMENT_STATUS',
     });
@@
-    expect(await verifyDocument(SIGNED_WRAPPED_DOCUMENT_DNS_DID_V3)).toMatchInlineSnapshot(`
+    const result = await verifyDocument(SIGNED_WRAPPED_DOCUMENT_DNS_DID_V3);
+    vi.restoreAllMocks();
+    expect(result).toMatchInlineSnapshot(`
       [
         ...
       ]
     `);
   });

Or add:

 describe.concurrent('V3 verify', () => {
+  afterEach(() => vi.restoreAllMocks());
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
describe.concurrent('V3 verify', () => {
it('should verify a DND_DID document and return fragments', async ({ expect }) => {
vi.spyOn(openAttestationDidSignedDocumentStatus, 'verify').mockResolvedValue({
data: {
details: {
issuance: {
did: 'did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90#controller',
issued: true,
},
revocation: {
revoked: false,
},
},
issuedOnAll: true,
revokedOnAny: false,
},
name: 'OpenAttestationDidSignedDocumentStatus',
status: 'VALID',
type: 'DOCUMENT_STATUS',
});
describe.concurrent('V3 verify', () => {
it('should verify a DND_DID document and return fragments', async ({ expect }) => {
vi.spyOn(openAttestationDidSignedDocumentStatus, 'verify').mockResolvedValueOnce({
data: {
details: {
issuance: {
did: 'did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90#controller',
issued: true,
},
revocation: {
revoked: false,
},
},
issuedOnAll: true,
revokedOnAny: false,
},
name: 'OpenAttestationDidSignedDocumentStatus',
status: 'VALID',
type: 'DOCUMENT_STATUS',
});
const result = await verifyDocument(SIGNED_WRAPPED_DOCUMENT_DNS_DID_V3);
vi.restoreAllMocks();
expect(result).toMatchInlineSnapshot(`
[
// …
]
`);
});
});
🤖 Prompt for AI Agents
In src/__tests__/core/verify.test.ts around lines 615 to 635, the test stubs
openAttestationDidSignedDocumentStatus.verify with mockResolvedValue but never
restores it, causing cross-test leakage; change the stub to
mockResolvedValueOnce (so it only affects this test) or call
restore/vi.restoreAllMocks after the test, or add an afterEach in this describe
that restores the mocked function (vi.restoreAllMocks or
openAttestationDidSignedDocumentStatus.verify.mockRestore()) to ensure
subsequent tests are unaffected.

Comment on lines +108 to +127

export const isObfuscated = (
document: WrappedDocument<OpenAttestationDocument> | SignedVerifiableCredential,
): boolean => {
if (isWrappedV3Document(document)) {
return !!document.proof.privacy?.obfuscated?.length;
}

if (isWrappedV2Document(document)) {
return !!document.privacy?.obfuscatedData?.length;
}

if (isSignedDocument(document)) {
return document.proof?.type === 'BbsBlsSignatureProof2020';
}

throw new Error(
'Unsupported document type: Can only check if there are obfuscated data from wrapped OpenAttestation v2, v3 documents and signed verifiable credentials.',
);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Extend isObfuscated to cover ECDSA-SD and proof arrays

The current logic detects BBS+ derived proofs only. With this PR defaulting to ECDSA-SD-2023 and enabling derived credentials, isObfuscated should also return true when a credential includes a DataIntegrityProof with cryptosuite 'ecdsa-sd-2023'. Also handle the case where proof is an array.

Apply this enhancement:

 export const isObfuscated = (
   document: WrappedDocument<OpenAttestationDocument> | SignedVerifiableCredential,
 ): boolean => {
   if (isWrappedV3Document(document)) {
     return !!document.proof.privacy?.obfuscated?.length;
   }
 
   if (isWrappedV2Document(document)) {
     return !!document.privacy?.obfuscatedData?.length;
   }
 
   if (isSignedDocument(document)) {
-    return document.proof?.type === 'BbsBlsSignatureProof2020';
+    const proofs = (Array.isArray(document.proof) ? document.proof : [document.proof]).filter(
+      Boolean,
+    );
+    return proofs.some(
+      (p: any) =>
+        p?.type === 'BbsBlsSignatureProof2020' ||
+        (p?.type === 'DataIntegrityProof' && p?.cryptosuite === 'ecdsa-sd-2023'),
+    );
   }
 
   throw new Error(
     'Unsupported document type: Can only check if there are obfuscated data from wrapped OpenAttestation v2, v3 documents and signed verifiable credentials.',
   );
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const isObfuscated = (
document: WrappedDocument<OpenAttestationDocument> | SignedVerifiableCredential,
): boolean => {
if (isWrappedV3Document(document)) {
return !!document.proof.privacy?.obfuscated?.length;
}
if (isWrappedV2Document(document)) {
return !!document.privacy?.obfuscatedData?.length;
}
if (isSignedDocument(document)) {
return document.proof?.type === 'BbsBlsSignatureProof2020';
}
throw new Error(
'Unsupported document type: Can only check if there are obfuscated data from wrapped OpenAttestation v2, v3 documents and signed verifiable credentials.',
);
};
export const isObfuscated = (
document: WrappedDocument<OpenAttestationDocument> | SignedVerifiableCredential,
): boolean => {
if (isWrappedV3Document(document)) {
return !!document.proof.privacy?.obfuscated?.length;
}
if (isWrappedV2Document(document)) {
return !!document.privacy?.obfuscatedData?.length;
}
if (isSignedDocument(document)) {
const proofs = (Array.isArray(document.proof) ? document.proof : [document.proof]).filter(
Boolean,
);
return proofs.some(
(p: any) =>
p?.type === 'BbsBlsSignatureProof2020' ||
(p?.type === 'DataIntegrityProof' && p?.cryptosuite === 'ecdsa-sd-2023'),
);
}
throw new Error(
'Unsupported document type: Can only check if there are obfuscated data from wrapped OpenAttestation v2, v3 documents and signed verifiable credentials.',
);
};
🤖 Prompt for AI Agents
In src/utils/documents/index.ts around lines 108 to 127, the isObfuscated
function only detects BBS+ proofs and assumes proof is a single object; update
the signed-document branch to treat proof as either an object or an array and
return true when any proof has type 'BbsBlsSignatureProof2020' OR has type
'DataIntegrityProof' with a cryptosuite field equal to 'ecdsa-sd-2023'
(case-sensitive), so the function covers ECDSA-SD derived credentials and proof
arrays; implement this by normalizing proof to an array, iterating it, and
checking both conditions before returning false or throwing the existing error
for unsupported types.

Comment on lines +47 to +57
let verificationResult = await verifyW3CSignature(document, verifierOptions);
let isDerived = true;
// Handle derivation if needed
if (
!verificationResult.verified &&
verificationResult.error?.includes(DERIVE_CREDENTIAL_ERROR)
) {
const derivedCredential = await deriveCredential(document, []);
verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
isDerived = false;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix inverted isDerived flag to report correct verification message

isDerived is initialized to true and flipped to false after derivation, which reverses the success message. Initialize to false and set to true only when a derivation occurs.

-      let verificationResult = await verifyW3CSignature(document, verifierOptions);
-      let isDerived = true;
+      let verificationResult = await verifyW3CSignature(document, verifierOptions);
+      let isDerived = false;
@@
-        const derivedCredential = await deriveCredential(document, []);
-        verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
-        isDerived = false;
+        const derivedCredential = await deriveCredential(document, []);
+        verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
+        isDerived = true;
@@
-            message: isDerived
-              ? 'Document verified successfully'
-              : 'Document verified after derivation',
+            message: isDerived
+              ? 'Document verified after derivation'
+              : 'Document verified successfully',

Also applies to: 65-67

🤖 Prompt for AI Agents
In src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts around
lines 47-57 (and also adjust similar logic at 65-67), the isDerived boolean is
inverted: it is initialized true and set false when a derivation occurs, causing
success messages to be reversed; initialize isDerived to false and set it to
true inside the branch where deriveCredential is called (i.e., when you replace
the document with derivedCredential.derived), and update any conditional
messages that rely on isDerived so they reflect "derived" only when isDerived
=== true.

Comment on lines +50 to +57
if (
!verificationResult.verified &&
verificationResult.error?.includes(DERIVE_CREDENTIAL_ERROR)
) {
const derivedCredential = await deriveCredential(document, []);
verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
isDerived = false;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid brittle error-string matching; derive on any ecdsa-sd-2023 failure

Relying on an exact substring ('Use deriveCredential() first') is fragile. If the upstream error text changes, we’ll miss the derive-and-retry path. Instead, derive when initial verification fails and the proof cryptosuite is ecdsa-sd-2023.

-      if (
-        !verificationResult.verified &&
-        verificationResult.error?.includes(DERIVE_CREDENTIAL_ERROR)
-      ) {
+      if (
+        !verificationResult.verified &&
+        (document as SignedVerifiableCredential)?.proof?.cryptosuite === CRYPTOSUITE
+      ) {
         const derivedCredential = await deriveCredential(document, []);
         verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
         isDerived = true;
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (
!verificationResult.verified &&
verificationResult.error?.includes(DERIVE_CREDENTIAL_ERROR)
) {
const derivedCredential = await deriveCredential(document, []);
verificationResult = await verifyW3CSignature(derivedCredential.derived, verifierOptions);
isDerived = false;
}
if (
!verificationResult.verified &&
(document as SignedVerifiableCredential)?.proof?.cryptosuite === CRYPTOSUITE
) {
const derivedCredential = await deriveCredential(document, []);
verificationResult = await verifyW3CSignature(
derivedCredential.derived,
verifierOptions
);
isDerived = true;
}
🤖 Prompt for AI Agents
In src/verify/fragments/document-integrity/ecdsaW3CSignatureIntegrity.ts around
lines 50 to 57, replace the brittle substring check against
verificationResult.error with a check that the initial verification failed AND
the document's (or proof's) cryptosuite/type indicates ecdsa-sd-2023; when both
are true call deriveCredential(document, []) and re-run verifyW3CSignature on
the derived credential, and set isDerived to true (not false). Ensure you read
the proof type from the document/proof in a null-safe way and only trigger
derive-and-retry for the ecdsa-sd-2023 cryptosuite.

Comment thread src/w3c/sign.ts
Comment on lines +16 to 23
cryptoSuite: CryptoSuiteName = 'ecdsa-sd-2023',
options?: {
mandatoryPointers?: string[];
},
): Promise<SigningResult> => {
// Call the signCredential function from the trustvc/w3c-vc package to sign the credential
return signCredential(credential, keyPair, cryptoSuite);
return signCredential(credential, keyPair, cryptoSuite, options);
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Guard ECDSA-SD–specific options and expose a stable options type

mandatoryPointers is suite-specific. A lightweight runtime check prevents silent misuse when a different suite is selected. Also, consider reusing a shared SignOptions interface from ./types to stabilize the API surface.

Apply this diff:

 export const signW3C = async (
   credential: RawVerifiableCredential,
   keyPair: PrivateKeyPair,
   cryptoSuite: CryptoSuiteName = 'ecdsa-sd-2023',
-  options?: {
-    mandatoryPointers?: string[];
-  },
+  options?: { mandatoryPointers?: string[] },
 ): Promise<SigningResult> => {
   // Call the signCredential function from the trustvc/w3c-vc package to sign the credential
-  return signCredential(credential, keyPair, cryptoSuite, options);
+  if (cryptoSuite !== 'ecdsa-sd-2023' && options?.mandatoryPointers?.length) {
+    throw new Error('mandatoryPointers is only supported for the ecdsa-sd-2023 cryptosuite.');
+  }
+  return signCredential(credential, keyPair, cryptoSuite, options);
 };

Additionally, define and reuse a shared type (in src/w3c/types.ts):

export interface SignOptions {
  mandatoryPointers?: string[];
}

Then adjust the signature and import here to options?: SignOptions.

🤖 Prompt for AI Agents
In src/w3c/sign.ts around lines 16 to 23, replace the inline options type with a
shared SignOptions imported from src/w3c/types.ts and add a runtime guard that
rejects or ignores mandatoryPointers when the cryptoSuite is not 'ecdsa-sd-2023'
to prevent silent misuse; specifically, import SignOptions, change the function
signature to options?: SignOptions, and before calling signCredential throw or
return a clear error if options?.mandatoryPointers is provided while cryptoSuite
!== 'ecdsa-sd-2023' (or else strip them and log a warning) so the API is stable
and suite-specific options are enforced at runtime.

@Moiz47 Moiz47 self-requested a review August 25, 2025 07:19
@rongquan1 rongquan1 merged commit a106501 into main Aug 25, 2025
20 of 21 checks passed
@rongquan1 rongquan1 deleted the release/v1-merge branch August 25, 2025 07:33
nghaninn pushed a commit that referenced this pull request Aug 25, 2025
## [2.0.0](v1.8.1...v2.0.0) (2025-08-25)

### ⚠ BREAKING CHANGES

* ecdsa and w3c data model 2.0

### Features

* ecdsa and w3c data model 2.0 ([#105](#105)) ([a106501](a106501))
@nghaninn

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants