{"version":3,"file":"SdJwtVcRecord.mjs","names":[],"sources":["../../../../src/modules/sd-jwt-vc/repository/SdJwtVcRecord.ts"],"sourcesContent":["import { decodeSdJwtSync } from '@sd-jwt/decode'\nimport { Hasher } from '../../../crypto'\nimport type { TagsBase } from '../../../storage/BaseRecord'\nimport { BaseRecord } from '../../../storage/BaseRecord'\nimport type { NonEmptyArray } from '../../../types'\nimport { JsonTransformer } from '../../../utils'\nimport { CredentialMultiInstanceState } from '../../../utils/credentialUseTypes'\nimport type { Constructable } from '../../../utils/mixins'\nimport { uuid } from '../../../utils/uuid'\nimport type { KnownJwaSignatureAlgorithm } from '../../kms'\nimport { decodeSdJwtVc } from '../decodeSdJwtVc'\nimport type { SdJwtVc } from '../SdJwtVcService'\nimport type { SdJwtVcTypeMetadata } from '../typeMetadata'\n\nexport type DefaultSdJwtVcRecordTags = {\n  vct: string\n\n  /**\n   * The sdAlg is the alg used for creating digests for selective disclosures\n   */\n  sdAlg: string\n\n  /**\n   * The alg is the alg used to sign the SD-JWT\n   */\n  alg: KnownJwaSignatureAlgorithm\n\n  /**\n   * @since 0.6 - tag was not defined before 0.6\n   */\n  multiInstanceState?: CredentialMultiInstanceState\n}\n\nexport type SdJwtVcRecordStorageProps = {\n  id?: string\n  createdAt?: Date\n  tags?: TagsBase\n\n  /**\n   * The SD-JWT VC instances to store on the record.\n   *\n   * NOTE that all instances should contain roughly the same data (e.g. exp can differ slighty), as they should be usable\n   * interchangeably for presentations (allowing single-use credentials and batch issuance).\n   */\n  credentialInstances: SdJwtVcRecordInstances\n\n  /**\n   * Optional VCT type metadata associated with the SD JWT VC instances, this type metadata is used for\n   * all SD JWT VC instances on this record.\n   *\n   * The type metadata is the result of resolving and merging the vct value and all `extends` values.\n   *\n   * NOTE: This may only include the latest VCT document, if the credential was stored before resolving\n   * `extends` claims was supported.\n   */\n  typeMetadata?: SdJwtVcTypeMetadata\n\n  /**\n   * The original chain of SD-JWT VC Type Metadata documents, ordered from the extending type to the last extended type.\n   * This is stored on the record to allow extensions to the type metadata (e.g. EUDI ARF TS12 for payments) to apply a\n   * custom merging strategy.\n   */\n  typeMetadataChain?: NonEmptyArray<SdJwtVcTypeMetadata>\n}\n\nexport type SdJwtVcRecordInstances = NonEmptyArray<{\n  compactSdJwtVc: string\n\n  /**\n   * The kms key id to which the credential is bound. If not defined it either:\n   * - uses a legacy key id (which can be calculated based on the key)\n   * - is bound to a did (which stores the kms key id on the did record)\n   */\n  kmsKeyId?: string\n}>\n\nexport class SdJwtVcRecord extends BaseRecord<DefaultSdJwtVcRecordTags> {\n  public static readonly type = 'SdJwtVcRecord'\n  public readonly type = SdJwtVcRecord.type\n\n  public credentialInstances!: SdJwtVcRecordInstances\n\n  /**\n   * Tracks the state of credential instances on this record.\n   *\n   * NOTE: This defaults to `CredentialMultiInstanceState.SingleInstanceUsed` for records that\n   * don't have a value set from before 0.6. We assume the credential has already been used.\n   */\n  public multiInstanceState = CredentialMultiInstanceState.SingleInstanceUsed\n\n  /**\n   * Only here for class transformation. If compactSdJwtVc is set we transform\n   * it to the new sdJwtVcs array format\n   */\n  private set compactSdJwtVc(compactSdJwtVc: string) {\n    this.credentialInstances = [\n      {\n        compactSdJwtVc,\n      },\n    ]\n  }\n\n  public typeMetadata?: SdJwtVcTypeMetadata\n\n  /**\n   * The original chain of SD-JWT VC Type Metadata documents, ordered from the extending type to the last extended type.\n   * This is stored on the record to allow extensions to the type metadata (e.g. EUDI ARF TS12 for payments) to apply a\n   * custom merging strategy.\n   */\n  public typeMetadataChain?: NonEmptyArray<SdJwtVcTypeMetadata>\n\n  public constructor(props: SdJwtVcRecordStorageProps) {\n    super()\n\n    if (props) {\n      this.id = props.id ?? uuid()\n      this.createdAt = props.createdAt ?? new Date()\n\n      this.credentialInstances = props.credentialInstances\n\n      // Set multiInstanceState based on the number of initial instances. We\n      // assume the instance is unused when the record is created.\n      this.multiInstanceState =\n        this.credentialInstances.length === 1\n          ? CredentialMultiInstanceState.SingleInstanceUnused\n          : CredentialMultiInstanceState.MultiInstanceFirstUnused\n\n      this.typeMetadata = props.typeMetadata\n      this.typeMetadataChain = props.typeMetadataChain\n      this._tags = props.tags ?? {}\n    }\n  }\n\n  public get firstCredential(): SdJwtVc {\n    return {\n      ...decodeSdJwtVc(this.credentialInstances[0].compactSdJwtVc, this.typeMetadata),\n      kmsKeyId: this.credentialInstances[0].kmsKeyId,\n    }\n  }\n\n  public static fromSdJwtVc(sdJwtVc: SdJwtVc) {\n    return new SdJwtVcRecord({\n      credentialInstances: [\n        {\n          compactSdJwtVc: sdJwtVc.compact,\n          kmsKeyId: sdJwtVc.kmsKeyId,\n        },\n      ],\n      typeMetadata: sdJwtVc.typeMetadata,\n    })\n  }\n\n  public get extendedVctValues() {\n    return this.typeMetadataChain\n      ? // Remove the first one, as that's not extended\n        this.typeMetadataChain.slice(1).map(({ vct }) => vct)\n      : this.typeMetadata?.extends\n        ? [this.typeMetadata.extends]\n        : []\n  }\n\n  public getTags() {\n    const sdjwt = decodeSdJwtSync(this.credentialInstances[0].compactSdJwtVc, Hasher.hash)\n    const vct = sdjwt.jwt.payload.vct as string\n    const sdAlg = sdjwt.jwt.payload._sd_alg as string | undefined\n    const alg = sdjwt.jwt.header.alg as KnownJwaSignatureAlgorithm\n\n    return {\n      ...this._tags,\n      vct,\n      extendedVctValues: this.extendedVctValues,\n      sdAlg: sdAlg ?? 'sha-256',\n      alg,\n      multiInstanceState: this.multiInstanceState,\n    }\n  }\n\n  public clone(): this {\n    return JsonTransformer.fromJSON(JsonTransformer.toJSON(this), this.constructor as Constructable<this>)\n  }\n\n  /**\n   * encoded is convenience method added to all credential records\n   */\n  public get encoded(): string {\n    return this.credentialInstances[0].compactSdJwtVc\n  }\n}\n"],"mappings":";;;;;;;;;;;;;AA4EA,IAAa,gBAAb,MAAa,sBAAsB,WAAqC;;;;;CAkBtE,IAAY,eAAe,gBAAwB;AACjD,OAAK,sBAAsB,CACzB,EACE,gBACD,CACF;;CAYH,AAAO,YAAY,OAAkC;AACnD,SAAO;OAlCO,OAAO,cAAc;OAU9B,qBAAqB,6BAA6B;AA0BvD,MAAI,OAAO;AACT,QAAK,KAAK,MAAM,MAAM,MAAM;AAC5B,QAAK,YAAY,MAAM,6BAAa,IAAI,MAAM;AAE9C,QAAK,sBAAsB,MAAM;AAIjC,QAAK,qBACH,KAAK,oBAAoB,WAAW,IAChC,6BAA6B,uBAC7B,6BAA6B;AAEnC,QAAK,eAAe,MAAM;AAC1B,QAAK,oBAAoB,MAAM;AAC/B,QAAK,QAAQ,MAAM,QAAQ,EAAE;;;CAIjC,IAAW,kBAA2B;AACpC,SAAO;GACL,GAAG,cAAc,KAAK,oBAAoB,GAAG,gBAAgB,KAAK,aAAa;GAC/E,UAAU,KAAK,oBAAoB,GAAG;GACvC;;CAGH,OAAc,YAAY,SAAkB;AAC1C,SAAO,IAAI,cAAc;GACvB,qBAAqB,CACnB;IACE,gBAAgB,QAAQ;IACxB,UAAU,QAAQ;IACnB,CACF;GACD,cAAc,QAAQ;GACvB,CAAC;;CAGJ,IAAW,oBAAoB;AAC7B,SAAO,KAAK,oBAER,KAAK,kBAAkB,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,IAAI,GACrD,KAAK,cAAc,UACjB,CAAC,KAAK,aAAa,QAAQ,GAC3B,EAAE;;CAGV,AAAO,UAAU;EACf,MAAM,QAAQ,gBAAgB,KAAK,oBAAoB,GAAG,gBAAgB,OAAO,KAAK;EACtF,MAAM,MAAM,MAAM,IAAI,QAAQ;EAC9B,MAAM,QAAQ,MAAM,IAAI,QAAQ;EAChC,MAAM,MAAM,MAAM,IAAI,OAAO;AAE7B,SAAO;GACL,GAAG,KAAK;GACR;GACA,mBAAmB,KAAK;GACxB,OAAO,SAAS;GAChB;GACA,oBAAoB,KAAK;GAC1B;;CAGH,AAAO,QAAc;AACnB,SAAO,gBAAgB,SAAS,gBAAgB,OAAO,KAAK,EAAE,KAAK,YAAmC;;;;;CAMxG,IAAW,UAAkB;AAC3B,SAAO,KAAK,oBAAoB,GAAG;;;cA5Gd,OAAO"}