Skip to content

feat: Add support for vctm header#32

Merged
vijayshiyani merged 2 commits intomainfrom
feat/vctm-support
May 29, 2025
Merged

feat: Add support for vctm header#32
vijayshiyani merged 2 commits intomainfrom
feat/vctm-support

Conversation

@vijayshiyani
Copy link
Contributor

@vijayshiyani vijayshiyani commented May 28, 2025

User description

Added support for embedding Type Metadata documents in the JWS unprotected header via the vctm parameter (as per SD-JWT VC Spec Section 6.3.5.


PR Type

Enhancement, Tests, Documentation


Description

  • Embed type metadata in vctm header

  • Extend createSignedVCSDJWT options signature

  • Remove deprecated createVCSDJWT method

  • Add tests covering vctm header behavior


Changes walkthrough 📝

Relevant files
Tests
issuer.spec.ts
Add vctm tests and clean imports                                                 

src/issuer.spec.ts

  • Clean up duplicate imports
  • Replace deprecated method calls
  • Add test for vctm header embedding
  • +47/-3   
    Enhancement
    issuer.ts
    Implement vctm header in createSignedVCSDJWT                         

    src/issuer.ts

  • Remove deprecated createVCSDJWT method
  • Add vctm header encoding logic
  • Update createSignedVCSDJWT signature
  • +31/-49 
    types.ts
    Add typeMetadataGlueDocuments to opts                                       

    src/types.ts

    • Introduce typeMetadataGlueDocuments option
    +1/-0     
    Documentation
    CHANGELOG.md
    Update changelog for vctm and removal                                       

    CHANGELOG.md

  • Document vctm header support addition
  • Note removal of deprecated method
  • +8/-0     

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • @vijayshiyani vijayshiyani marked this pull request as ready for review May 29, 2025 03:13
    @vijayshiyani vijayshiyani merged commit d062ecf into main May 29, 2025
    2 checks passed
    @Meeco Meeco deleted a comment from QodoAI-Agent Jun 26, 2025
    @leikind
    Copy link

    leikind commented Jun 26, 2025

    using this PR for AI PR agent tests... Please ignore

    @Meeco Meeco deleted a comment from QodoAI-Agent Jun 26, 2025
    @leikind
    Copy link

    leikind commented Jun 26, 2025

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Duplicate Method

    The file includes two definitions of createSignedVCSDJWT, which will cause a duplicate method error. Remove the old implementation or consolidate into a single method.

    async createSignedVCSDJWT(opts: CreateSignedJWTOpts): Promise<JWT> {
      const {
        vcClaims,
        sdJWTPayload,
        sdVCClaimsDisclosureFrame = {},
        saltGenerator,
        sdJWTHeader,
        typeMetadataGlueDocuments,
      } = opts;
      if (!vcClaims) throw new SDJWTVCError('vcClaims is required');
      if (!sdJWTPayload) throw new SDJWTVCError('sdJWTPayload is required');
    
      this.validateVCClaims(vcClaims as VCClaims);
      this.validateSDJWTPayload(sdJWTPayload);
      this.validateSDVCClaimsDisclosureFrame(sdVCClaimsDisclosureFrame);
    
      const header: JWTHeaderParameters & { vctm?: string[] } = {
        ...sdJWTHeader,
        typ: Issuer.SD_JWT_TYP,
        alg: this.signer.alg,
      };
    
      if (typeMetadataGlueDocuments && typeMetadataGlueDocuments.length > 0) {
        header.vctm = typeMetadataGlueDocuments.map((doc) => {
          const docString = typeof doc === 'string' ? doc : JSON.stringify(doc);
          return base64encode(docString);
        });
      }
    
      try {
        const jwt = await issueSDJWT(header, { ...sdJWTPayload, ...vcClaims }, sdVCClaimsDisclosureFrame, {
          signer: this.signer.callback,
          hash: {
            alg: this.hasher.alg,
            callback: this.hasher.callback,
          },
          cnf: sdJWTPayload?.cnf,
          generateSalt: saltGenerator,
        });
    
        return jwt;
      } catch (error: any) {
    Encoding Format

    Ensure that base64encode produces a URL‐safe base64 string suitable for JWS headers, as required by the SD-JWT VC specification.

    if (typeMetadataGlueDocuments && typeMetadataGlueDocuments.length > 0) {
      header.vctm = typeMetadataGlueDocuments.map((doc) => {
        const docString = typeof doc === 'string' ? doc : JSON.stringify(doc);
        return base64encode(docString);
      });
    }

    @leikind
    Copy link

    leikind commented Jun 27, 2025

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Impact
    General
    Validate metadata documents before encoding

    Add validation to ensure each type metadata document contains required fields before
    encoding. The current implementation blindly encodes any object or string without
    validating the structure or content.

    src/issuer.ts [62-67]

     if (typeMetadataGlueDocuments && typeMetadataGlueDocuments.length > 0) {
       header.vctm = typeMetadataGlueDocuments.map((doc) => {
         const docString = typeof doc === 'string' ? doc : JSON.stringify(doc);
    +    if (!docString.trim()) {
    +      throw new SDJWTVCError('Type metadata document cannot be empty');
    +    }
         return base64encode(docString);
       });
     }
    Suggestion importance[1-10]: 4

    __

    Why: The suggestion adds basic validation for empty documents, which improves robustness. However, it only checks for empty strings and doesn't validate the actual structure or required fields as mentioned in the description.

    Low
    Add JSON parsing error handling

    Add error handling around JSON parsing operations to prevent test failures when
    base64 decoding returns invalid JSON. The current code assumes successful parsing
    without handling potential JSON syntax errors.

    src/issuer.spec.ts [148-150]

    -const decodedDoc1 = JSON.parse(base64decode((headerWithVctm.vctm as any[])[0]));
    +let decodedDoc1, decodedDoc2;
    +try {
    +  decodedDoc1 = JSON.parse(base64decode((headerWithVctm.vctm as any[])[0]));
    +  decodedDoc2 = JSON.parse(base64decode((headerWithVctm.vctm as any[])[1]));
    +} catch (error) {
    +  throw new Error(`Failed to parse decoded metadata documents: ${error}`);
    +}
     
    -const decodedDoc2 = JSON.parse(base64decode((headerWithVctm.vctm as any[])[1]));
    -
    Suggestion importance[1-10]: 3

    __

    Why: While error handling is generally good practice, this is test code where failures should be visible. The suggestion adds unnecessary complexity to a test that should fail if the JSON parsing fails, as that would indicate a real issue.

    Low

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

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    3 participants