fix: mandatory status and expiry pointers - #159
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe change updates W3C package versions and adds presentation tests for selective disclosure. The tests verify that revocation and expiration metadata remain present and that signing rejects revoked or expired credentials. ChangesCredential Policy Validation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
…e presented Selective disclosure lets a holder omit any statement the issuer did not mark mandatory, and the credential still verifies. `credentialStatus` and the end of the validity window were not mandatory, so a holder could derive them away and present a revoked or expired credential that passed every check: issued with credentialStatus index 5 (revoked) holder derives -> credentialStatus present? false presenting the stripped credential -> SIGNED DOCUMENT_INTEGRITY: VALID / DOCUMENT_STATUS: VALID / ISSUER_IDENTITY: VALID The removal is undetectable — the derived proof records nothing about what was withheld, and dropping the then-unused status-list `@context` entry leaves the canonical RDF, and so the signature, intact. Verification cannot catch it, so the fix is at issuance: @trustvc/w3c-vc 2.4.2 adds `/credentialStatus`, `/validUntil` and `/expirationDate` to its core mandatory pointers. Both attacks are now refused through the trustvc API: status survived the strip attempt: true -> REFUSED: credential at index 0 has been revocation (credentialStatus). expiry survived the strip attempt: true -> REFUSED: credential at index 0 has expired (2021-01-01T00:00:00Z). Add two presentation tests for this. They are not re-testing w3c-vc: they pin a trustvc-level guarantee that now depends on another package's issuance defaults. Without them, a downgrade or a change to that default leaves every trustvc test passing while the hole silently reopens. Each asserts the field SURVIVED the strip attempt before asserting the refusal, so a failure says which link broke. Note this changes derivation output for consumers: a credential with a status or an expiry now discloses those fields whether or not the holder selected them. It is also not retroactive — anything already signed stays strippable and must be reissued. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29f6389 to
a46ae8e
Compare
|
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (12)
src/eip7702-functions/token-registry-functions-gasless/mint.ts (2)
10-15: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueType the address fields as
0x-prefixed strings.
paymasterAddressandtokenRegistryAddressare typed asstring, then cast to`0x${string}`at lines 46 and 52. The casts hide malformed input.DeployTokenRegistryGaslessOptionsinsrc/eip7702-functions/deploy/token-registry.tsalready uses the template literal type. Use the same type here and drop the casts.Also applies to: 45-60
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/eip7702-functions/token-registry-functions-gasless/mint.ts` around lines 10 - 15, Update MintGaslessOptions.paymasterAddress and tokenRegistryAddress to use the `0x${string}` template-literal type, matching DeployTokenRegistryGaslessOptions. Remove the corresponding casts at the mint call sites so malformed address inputs are rejected by the type system.
6-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate
GaslessSmartAccountClientinterface in two modules. Both files declare the same non-exported client interface. The declarations can drift apart, and consumers of the public API cannot type the client they must pass in.
src/eip7702-functions/token-registry-functions-gasless/mint.ts#L6-L8: remove the local declaration and import the shared exported type.src/eip7702-functions/deploy/token-registry.ts#L4-L6: remove the local declaration and import the same shared exported type.Define and export the type once, for example in a shared
types.tsundersrc/eip7702-functions, and re-export it fromsrc/eip7702-functions/index.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/eip7702-functions/token-registry-functions-gasless/mint.ts` around lines 6 - 8, Define and export a single GaslessSmartAccountClient type in shared eip7702-functions types, re-export it from the package index, and replace the local declarations with imports in src/eip7702-functions/token-registry-functions-gasless/mint.ts lines 6-8 and src/eip7702-functions/deploy/token-registry.ts lines 4-6. Ensure both modules use the same shared exported type..github/workflows/linters.yml (1)
44-44: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winDo not install Commitlint with
npm install --force.
@commitlint/config-conventionalis already declared indevDependenciesand locked inpackage-lock.json, so this workflow lets the action install an unsealed21.2.0copy instead of using the repository dependency. Remove the package specifier and--force, and runnpm ci --ignore-scriptsincommit-lint.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/linters.yml at line 44, Update the commit-lint job’s dependency installation command to use the repository-locked dependencies: replace the forced package-specific npm install with npm ci --ignore-scripts, removing both the package specifier and --force.Source: Linters/SAST tools
src/__tests__/e2e/fixtures/sample-boe-credential.ts (1)
14-21: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low valueConfirm the key is a throwaway test key.
Betterleaks flags line 20. The comment states the key matches existing test fixtures, so this looks intentional. Add an inline suppression comment for the secret scanner so future scans stay clean, and confirm the key is never used outside tests.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/__tests__/e2e/fixtures/sample-boe-credential.ts` around lines 14 - 21, Keep SAMPLE_BOE_SIGNING_KEY limited to test fixtures and verify it is not referenced by production code. Add the repository’s recognized inline secret-scanner suppression comment directly beside secretKeyMultibase, documenting that this is an intentional throwaway test key.Source: Linters/SAST tools
src/__tests__/obligation-registry-functions/deploy.test.ts (1)
44-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the ethers v5 deployment branch.
Both tests set
isV6EthersProvidertotrue. The v5 branch insrc/obligation-registry-functions/deploy.ts(lines 92-101 and 155-170), includinggetDeployedAddress, stays untested. Add a case withisV6EthersProviderreturningfalseand a mock contract exposingdeployTransaction.wait()andaddress.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/__tests__/obligation-registry-functions/deploy.test.ts` around lines 44 - 77, Add a test for the ethers v5 path in deployObligationRegistry by making isV6EthersProvider return false and mocking the deployed contract with address plus deployTransaction.wait(). Assert the resolved registry and escrow factory addresses and verify deployment arguments, covering the getDeployedAddress flow while keeping the existing v6 test unchanged.src/__tests__/verify/obligationRecordVerifier.utils.test.ts (1)
28-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a case for the chain-ID mismatch branch.
Every test passes
chainId: 80002, which matches the mocked provider network. The guard inisTokenMintedOnObligationRegistrythat returnsUNRECOGNIZED_DOCUMENTon a chain mismatch stays untested. Add a case with a mismatchedchainIdand one that omitschainId.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/__tests__/verify/obligationRecordVerifier.utils.test.ts` around lines 28 - 85, The tests for isTokenMintedOnObligationRegistry cover only the matching chain ID; add cases using a mismatched chainId and omitting chainId to exercise the chain-mismatch guard. Assert both return minted: false with the UNRECOGNIZED_DOCUMENT status, preserving the existing matching-chain tests.src/obligation-registry-functions/deploy.ts (2)
37-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
getDeployedAddressnever reads the receipt.The function returns
fallbackAddressfirst. The only call site (line 167) always passescontract.address, which ethers v5 always populates. The receipt branch and the error path are therefore unreachable. The parameter name also implies the opposite precedence.Prefer the receipt address, then fall back to
contract.address, and reuse the helper indeployObligationEscrowFactory(line 99) for consistent behavior.♻️ Proposed refactor
const getDeployedAddress = ( receipt: ContractReceiptV5 | ContractReceiptV6, fallbackAddress?: string, ): string => { - if (fallbackAddress) { - return fallbackAddress; - } - const contractAddress = 'contractAddress' in receipt ? receipt.contractAddress || undefined : undefined; - if (!contractAddress) { + const resolved = contractAddress ?? fallbackAddress; + if (!resolved) { throw new Error('Unable to resolve deployed contract address from receipt'); } - return contractAddress; + return resolved; };return { - obligationEscrowFactoryAddress: contract.address, + obligationEscrowFactoryAddress: getDeployedAddress(receipt, contract.address), receipt, };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/obligation-registry-functions/deploy.ts` around lines 37 - 53, Update getDeployedAddress to prefer a valid contractAddress from the receipt and use fallbackAddress only when the receipt does not provide one, preserving the existing error when neither exists. Rename the fallback parameter if needed to reflect its role, and replace the inline address-resolution logic in deployObligationEscrowFactory with this helper so both deployment paths share the same behavior.
114-126: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueReuse the resolved chain ID for the internal escrow factory deployment.
If
options.escrowFactoryAddressis absent,deployObligationEscrowFactoryresolves the chain ID and the fee options itself (lines 63-69).deployObligationRegistrythen resolves them again. That causes two extra provider calls per deployment. ResolvechainIdbefore line 115 and pass it inoptions.♻️ Proposed refactor
- let obligationEscrowFactoryAddress = options.escrowFactoryAddress; + const chainId = options.chainId ?? ((await getChainIdSafe(signer)) as unknown as CHAIN_ID); + + let obligationEscrowFactoryAddress = options.escrowFactoryAddress; if (!obligationEscrowFactoryAddress) { - const deployedFactory = await deployObligationEscrowFactory(signer, options); + const deployedFactory = await deployObligationEscrowFactory(signer, { ...options, chainId }); obligationEscrowFactoryAddress = deployedFactory.obligationEscrowFactoryAddress; } - const chainId = options.chainId ?? ((await getChainIdSafe(signer)) as unknown as CHAIN_ID); const txOptions = await getTxOptions(🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/obligation-registry-functions/deploy.ts` around lines 114 - 126, Resolve chainId before the conditional escrow-factory deployment in deployObligationRegistry, and pass that resolved value through the options supplied to deployObligationEscrowFactory so its existing chain and fee-option resolution is reused. Then use the same chainId for getTxOptions, preserving the provided options.escrowFactoryAddress path without unnecessary provider calls.src/core/documentBuilder.ts (1)
379-393: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: match the unsupported-registry error by type, not by message text.
withRegistryNetworkErrorcompareserror.messageto a string. If the message text changes in one place only, a genuine unsupported-registry error is reported as a network error. A dedicated error class or a sentinel property removes that coupling.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/documentBuilder.ts` around lines 379 - 393, Update withRegistryNetworkError to identify unsupported-registry failures using a dedicated error type or sentinel property instead of comparing error.message with unsupportedRegistryError. Preserve rethrowing the original unsupported-registry error and continue wrapping other failures with networkError.src/__tests__/obligation-registry-functions/mint.test.ts (1)
114-129: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: the v6 matrix run repeats the v5 signer case.
This test always creates a
WalletV5signer, so the ethers v6 run repeats the same assertion. Move the case outsidedescribe.each, or create aWalletV6signer whenethersVersion === 'v6'.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/__tests__/obligation-registry-functions/mint.test.ts` around lines 114 - 129, Update the “throws when provider is missing” test in the obligation registry test suite so it does not duplicate the WalletV5 case during the ethers v6 matrix run. Move the test outside describe.each, or select WalletV6 when ethersVersion is v6 while preserving the existing Provider is required assertion.src/__tests__/obligation-registry-functions/ownerOf.test.ts (1)
15-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: add ethers v6 coverage.
The sibling obligation-registry tests run a v5/v6 provider matrix. This file tests only ethers v5, so the v6 contract-read path for
ownerOfObligationRegistryis untested.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/__tests__/obligation-registry-functions/ownerOf.test.ts` around lines 15 - 43, Extend the ownerOfObligationRegistry test suite to cover both ethers v5 and v6 provider paths, matching the provider matrix used by sibling obligation-registry tests. Parameterize or duplicate the existing owner-address and missing-registry-address cases while preserving their current assertions and setup behavior.src/utils/documents/obligation.ts (1)
26-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueOptional: reuse
getObligationRecordsCredentialStatushere.
isObligationRecordrepeats the credential-status normalization already implemented at line 21. Delegating keeps one normalization path.♻️ Proposed simplification
if (!isSignedDocument(document)) { return false; } - - const credentialStatuses = Array.isArray(document.credentialStatus) - ? document.credentialStatus - : [document.credentialStatus]; - - return credentialStatuses.some((cs) => isObligationRecordCredentialStatus(cs)); + return getObligationRecordsCredentialStatus(document) !== undefined; };🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/utils/documents/obligation.ts` around lines 26 - 38, Update isObligationRecord to reuse getObligationRecordsCredentialStatus for credential-status normalization instead of rebuilding the array locally, then apply isObligationRecordCredentialStatus to the returned normalized statuses while preserving the existing signed-document guard.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Line 35: Update the Table of Contents entry for Gasless Operations to replace
the invalid `#overview-1` fragment with the anchor generated for its Overview
heading, leaving the displayed link text unchanged.
- Line 468: Correct the obsolete section references in README.md: at lines
468-468 and 989-989, change §7c to §8c; at lines 989-989, also change §4 to §5;
and at lines 1585-1585, change “section 7” to “section 8”.
In `@src/__tests__/e2e/obligation-registry-functions/statusLifecycle.e2e.test.ts`:
- Around line 51-63: In the before hook, update the setup order around
hardhat_reset and evm_setAutomine: call hardhat_reset first, then enable
automining with evm_setAutomine so the setting persists for the suite. Leave
signer creation and deployment unchanged.
In `@src/__tests__/obligation-registry-functions/rejectTransfers.test.ts`:
- Around line 55-64: Add an assertion in the
“rejectTransferHolderObligationRegistry with remarks” test verifying that the
encryption function is called with the provided remarks, following the
established pattern in lifecycle.test.ts and mint.test.ts while retaining the
transaction-hash assertion.
In `@src/core/documentBuilder.ts`:
- Around line 109-113: Run Prettier on the changed code: in
src/core/documentBuilder.ts lines 109-113, format the selectedStatusType union
declaration; in
src/verify/fragments/document-status/obligationRecords/obligationRecordVerifier.ts
lines 105-110, format the credentialStatuses.some callback. No behavioral
changes are needed.
- Around line 173-198: Add a symmetric mixing guard to credentialStatus
immediately after its isSigned check, rejecting calls when selectedStatusType is
'obligationRecords' with the same configuration error used by
obligationCredentialStatus. Preserve the existing credentialStatus configuration
flow for all other status types.
In `@src/core/endorsement-chain/fetchEscrowTransfer.ts`:
- Around line 163-170: Invoke each status filter factory before adding it to
allFilters in the includeObligationStatus branch of fetchEscrowTransfer, so
queryFilter receives instantiated event filters rather than the factory
functions themselves. Preserve the existing four status filters and their
ordering.
In `@src/eip7702-functions/deploy/platform-paymaster.ts`:
- Around line 66-78: Validate the resolved platformAddress immediately after its
assignment in the writeContract branch, alongside the existing publicClient
guard. Throw an explicit error when neither options.platformAddress nor
signer.account?.address provides an address, and preserve the existing
transaction flow for valid addresses.
In `@src/eip7702-functions/platform-paymaster-functions/admin.ts`:
- Around line 34-41: Update the v6 branch in the transaction helper containing
isV6EthersProvider to await tx.wait() before returning the transaction hash,
matching the v5 confirmation semantics and deployPlatformPaymaster convention.
Adjust the corresponding v6 expectations in the admin tests so setUserWhitelist
and addRegistry resolve only after confirmation.
In `@src/eip7702-functions/token-registry-functions-gasless/mint.ts`:
- Line 43: Update the encryptedRemarks expression in the mint flow to handle
optional options.id without a non-null assertion, matching the existing
token-registry mint behavior by using an empty-string fallback or explicitly
rejecting remarks when no id is provided.
In `@src/eip7702-functions/token-registry-functions-gasless/transfer.ts`:
- Line 37: Update the encryption calls to use the existing empty-key fallback
when options.id is omitted, while preserving the current '0x' result when
remarks are absent. Apply this in transfer.ts at lines 37, 70, 103, and 140;
rejectTransfers.ts at lines 34, 67, and 100; and returnToken.ts at lines 39, 73,
and 107, so encrypt never receives undefined.
In `@src/obligation-registry-functions/status.ts`:
- Around line 25-28: Update the async status handler to use the supplied
_params.tokenId when resolving the escrow through getEscrowContract, rather than
relying on contractOptions.tokenId. Ensure params.tokenId takes precedence when
both values are present, while preserving the existing read(contract, options)
behavior.
In `@src/utils/documents/index.ts`:
- Around line 35-41: Update the credentialStatuses validation to require at
least one credential status before evaluating every(...). Ensure an empty
document.credentialStatus array returns false, while preserving the existing
status checks for non-empty arrays.
In
`@src/verify/fragments/document-status/obligationRecords/obligationRecordVerifier.ts`:
- Around line 39-70: Update the credentialStatuses mapping in the
verificationResult flow to validate credentialStatus.tokenId before constructing
tokenId. If it is absent or invalid, throw the same UNRECOGNIZED_DOCUMENT
CodedError used by the obligationRegistry and chainId guards; otherwise derive
the hex value without duplicating an existing 0x prefix, then pass it to
isTokenMintedOnObligationRegistry.
In
`@src/verify/fragments/document-status/obligationRecords/obligationRecordVerifier.types.ts`:
- Around line 27-29: Define ObligationRecordsVerificationFragment directly as
ObligationRecordsResultFragment, removing the redundant single-member union
while preserving the existing type alias.
In `@src/verify/fragments/document-status/obligationRecords/utils.ts`:
- Around line 77-81: Update the catch block around ownerOf in the
obligation-record verification flow so only the known nonexistent-token revert
is converted via notMintedReason. Distinguish that expected revert before
calling decodeError; rethrow RPC transport failures, timeouts, rate limits, and
unexpected contract errors instead of returning a non-minted result.
---
Nitpick comments:
In @.github/workflows/linters.yml:
- Line 44: Update the commit-lint job’s dependency installation command to use
the repository-locked dependencies: replace the forced package-specific npm
install with npm ci --ignore-scripts, removing both the package specifier and
--force.
In `@src/__tests__/e2e/fixtures/sample-boe-credential.ts`:
- Around line 14-21: Keep SAMPLE_BOE_SIGNING_KEY limited to test fixtures and
verify it is not referenced by production code. Add the repository’s recognized
inline secret-scanner suppression comment directly beside secretKeyMultibase,
documenting that this is an intentional throwaway test key.
In `@src/__tests__/obligation-registry-functions/deploy.test.ts`:
- Around line 44-77: Add a test for the ethers v5 path in
deployObligationRegistry by making isV6EthersProvider return false and mocking
the deployed contract with address plus deployTransaction.wait(). Assert the
resolved registry and escrow factory addresses and verify deployment arguments,
covering the getDeployedAddress flow while keeping the existing v6 test
unchanged.
In `@src/__tests__/obligation-registry-functions/mint.test.ts`:
- Around line 114-129: Update the “throws when provider is missing” test in the
obligation registry test suite so it does not duplicate the WalletV5 case during
the ethers v6 matrix run. Move the test outside describe.each, or select
WalletV6 when ethersVersion is v6 while preserving the existing Provider is
required assertion.
In `@src/__tests__/obligation-registry-functions/ownerOf.test.ts`:
- Around line 15-43: Extend the ownerOfObligationRegistry test suite to cover
both ethers v5 and v6 provider paths, matching the provider matrix used by
sibling obligation-registry tests. Parameterize or duplicate the existing
owner-address and missing-registry-address cases while preserving their current
assertions and setup behavior.
In `@src/__tests__/verify/obligationRecordVerifier.utils.test.ts`:
- Around line 28-85: The tests for isTokenMintedOnObligationRegistry cover only
the matching chain ID; add cases using a mismatched chainId and omitting chainId
to exercise the chain-mismatch guard. Assert both return minted: false with the
UNRECOGNIZED_DOCUMENT status, preserving the existing matching-chain tests.
In `@src/core/documentBuilder.ts`:
- Around line 379-393: Update withRegistryNetworkError to identify
unsupported-registry failures using a dedicated error type or sentinel property
instead of comparing error.message with unsupportedRegistryError. Preserve
rethrowing the original unsupported-registry error and continue wrapping other
failures with networkError.
In `@src/eip7702-functions/token-registry-functions-gasless/mint.ts`:
- Around line 10-15: Update MintGaslessOptions.paymasterAddress and
tokenRegistryAddress to use the `0x${string}` template-literal type, matching
DeployTokenRegistryGaslessOptions. Remove the corresponding casts at the mint
call sites so malformed address inputs are rejected by the type system.
- Around line 6-8: Define and export a single GaslessSmartAccountClient type in
shared eip7702-functions types, re-export it from the package index, and replace
the local declarations with imports in
src/eip7702-functions/token-registry-functions-gasless/mint.ts lines 6-8 and
src/eip7702-functions/deploy/token-registry.ts lines 4-6. Ensure both modules
use the same shared exported type.
In `@src/obligation-registry-functions/deploy.ts`:
- Around line 37-53: Update getDeployedAddress to prefer a valid contractAddress
from the receipt and use fallbackAddress only when the receipt does not provide
one, preserving the existing error when neither exists. Rename the fallback
parameter if needed to reflect its role, and replace the inline
address-resolution logic in deployObligationEscrowFactory with this helper so
both deployment paths share the same behavior.
- Around line 114-126: Resolve chainId before the conditional escrow-factory
deployment in deployObligationRegistry, and pass that resolved value through the
options supplied to deployObligationEscrowFactory so its existing chain and
fee-option resolution is reused. Then use the same chainId for getTxOptions,
preserving the provided options.escrowFactoryAddress path without unnecessary
provider calls.
In `@src/utils/documents/obligation.ts`:
- Around line 26-38: Update isObligationRecord to reuse
getObligationRecordsCredentialStatus for credential-status normalization instead
of rebuilding the array locally, then apply isObligationRecordCredentialStatus
to the returned normalized statuses while preserving the existing
signed-document guard.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 16b3ab73-dea0-4e63-ace9-d44c9e40f0f9
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (77)
.github/workflows/ci.yml.github/workflows/linters.yml.github/workflows/publish.yml.github/workflows/tests.ymlCHANGELOG.mdOA-v3-document-sepolia.jsonREADME.mdpackage.jsonrelease.config.jssrc/__tests__/core/documentBuilder.test.tssrc/__tests__/core/verify.amoy.test.tssrc/__tests__/core/verify.test.tssrc/__tests__/e2e/fixtures/sample-boe-credential.tssrc/__tests__/e2e/obligation-registry-functions/fixtures.tssrc/__tests__/e2e/obligation-registry-functions/statusLifecycle.e2e.test.tssrc/__tests__/e2e/obligation-registry-functions/transfer.e2e.test.tssrc/__tests__/e2e/utils.tssrc/__tests__/eip7702-functions/admin.test.tssrc/__tests__/eip7702-functions/deploy.test.tssrc/__tests__/eip7702-functions/mint.test.tssrc/__tests__/eip7702-functions/rejectTransfers.test.tssrc/__tests__/eip7702-functions/returnToken.test.tssrc/__tests__/eip7702-functions/transfer.test.tssrc/__tests__/fixtures/endorsement-chain.tssrc/__tests__/obligation-registry-functions/deploy.test.tssrc/__tests__/obligation-registry-functions/fixtures.tssrc/__tests__/obligation-registry-functions/lifecycle.test.tssrc/__tests__/obligation-registry-functions/mint.test.tssrc/__tests__/obligation-registry-functions/ownerOf.test.tssrc/__tests__/obligation-registry-functions/rejectTransfers.test.tssrc/__tests__/obligation-registry-functions/returnToken.test.tssrc/__tests__/obligation-registry-functions/status.test.tssrc/__tests__/obligation-registry-functions/transfers.test.tssrc/__tests__/utils/documents/index.test.tssrc/__tests__/verify/obligationRecordVerifier.utils.test.tssrc/__tests__/w3c/presentation.test.tssrc/core/documentBuilder.tssrc/core/endorsement-chain/fetchEscrowTransfer.tssrc/core/endorsement-chain/helpers.tssrc/core/endorsement-chain/index.tssrc/core/endorsement-chain/obligation.tssrc/core/endorsement-chain/types.tssrc/core/endorsement-chain/useEndorsementChain.tssrc/eip7702-functions/deploy/index.tssrc/eip7702-functions/deploy/platform-paymaster.tssrc/eip7702-functions/deploy/token-registry.tssrc/eip7702-functions/index.tssrc/eip7702-functions/platform-paymaster-functions/admin.tssrc/eip7702-functions/platform-paymaster-functions/index.tssrc/eip7702-functions/token-registry-functions-gasless/index.tssrc/eip7702-functions/token-registry-functions-gasless/mint.tssrc/eip7702-functions/token-registry-functions-gasless/rejectTransfers.tssrc/eip7702-functions/token-registry-functions-gasless/returnToken.tssrc/eip7702-functions/token-registry-functions-gasless/transfer.tssrc/index.tssrc/obligation-registry-functions/deploy.tssrc/obligation-registry-functions/index.tssrc/obligation-registry-functions/lifecycle.tssrc/obligation-registry-functions/mint.tssrc/obligation-registry-functions/ownerOf.tssrc/obligation-registry-functions/rejectTransfers.tssrc/obligation-registry-functions/returnToken.tssrc/obligation-registry-functions/status.tssrc/obligation-registry-functions/transfer.tssrc/obligation-registry-functions/types.tssrc/obligation-registry-functions/utils.tssrc/token-registry-v5/contracts.tssrc/utils/documents/index.tssrc/utils/documents/obligation.tssrc/verify/fragments/document-status/obligationRecords/obligationRecordVerifier.tssrc/verify/fragments/document-status/obligationRecords/obligationRecordVerifier.types.tssrc/verify/fragments/document-status/obligationRecords/utils.tssrc/verify/fragments/document-status/obligationRecords/verifierHelpers.tssrc/verify/fragments/document-status/transferableRecords/transferableRecordVerifier.tssrc/verify/fragments/document-status/transferableRecords/utils.tssrc/verify/fragments/index.tssrc/verify/verify.ts
|
@coderabbitai full review |
✅ Action performedFull review finished. |
## [2.15.1](v2.15.0...v2.15.1) (2026-08-07) ### Bug Fixes * bump w3c-vc to 2.4.2 so revoked and expired credentials cannot be presented ([#159](#159)) ([b9646bc](b9646bc))
|
🎉 This PR is included in version 2.15.1 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Sync the 2.15.1 patch from main into the beta line: bump @trustvc/w3c-vc to 2.4.2 so revoked and expired credentials cannot be presented (#159). Conflict resolutions: - package.json: keep beta's version (2.16.0-beta.2, the higher line); take main's @trustvc/w3c-vc ^2.4.2; keep beta's @trustvc/eip7702 dep - package-lock.json: kept beta's cross-platform lockfile, bumped w3c-vc to 2.4.2 via `npm install --package-lock-only` (all 26 esbuild platforms preserved) - CHANGELOG.md: kept both histories; inserted the 2.15.1 section before 2.15.0 - src/__tests__/w3c/presentation.test.ts: main's #159 test merged cleanly Verified: type-check, lint, npm ci clean, w3c-vc 2.4.2 installed, VP tests 32/32 pass (incl. the revoked/expired presentation checks). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 2.16.0-beta.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |



Summary by CodeRabbit
Bug Fixes
Tests