UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

1 lines • 7.77 kB
{"version":3,"file":"SdJwtVcRecord.mjs","names":[],"sources":["../../../../src/modules/sd-jwt-vc/repository/SdJwtVcRecord.ts"],"sourcesContent":["import { decodeSdJwtSync } from '@sd-jwt/core'\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;EACjD,KAAK,sBAAsB,CACzB,EACE,eACF,CACF;CACF;CAWA,YAAmB,OAAkC;EACnD,MAAM;EAlCR,KAAgB,OAAO,cAAc;EAUrC,KAAO,qBAAA;EA0BL,IAAI,OAAO;GACT,KAAK,KAAK,MAAM,MAAM,KAAK;GAC3B,KAAK,YAAY,MAAM,6BAAa,IAAI,KAAK;GAE7C,KAAK,sBAAsB,MAAM;GAIjC,KAAK,qBACH,KAAK,oBAAoB,WAAW,IAAA,yBAAA;GAItC,KAAK,eAAe,MAAM;GAC1B,KAAK,oBAAoB,MAAM;GAC/B,KAAK,QAAQ,MAAM,QAAQ,CAAC;EAC9B;CACF;CAEA,IAAW,kBAA2B;EACpC,OAAO;GACL,GAAG,cAAc,KAAK,oBAAoB,EAAE,CAAC,gBAAgB,KAAK,YAAY;GAC9E,UAAU,KAAK,oBAAoB,EAAE,CAAC;EACxC;CACF;CAEA,OAAc,YAAY,SAAkB;EAC1C,OAAO,IAAI,cAAc;GACvB,qBAAqB,CACnB;IACE,gBAAgB,QAAQ;IACxB,UAAU,QAAQ;GACpB,CACF;GACA,cAAc,QAAQ;EACxB,CAAC;CACH;CAEA,IAAW,oBAAoB;EAC7B,OAAO,KAAK,oBAER,KAAK,kBAAkB,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,GAAG,IACpD,KAAK,cAAc,UACjB,CAAC,KAAK,aAAa,OAAO,IAC1B,CAAC;CACT;CAEA,UAAiB;EACf,MAAM,QAAQ,gBAAgB,KAAK,oBAAoB,EAAE,CAAC,gBAAgB,OAAO,IAAI;EACrF,MAAM,MAAM,MAAM,IAAI,QAAQ;EAC9B,MAAM,QAAQ,MAAM,IAAI,QAAQ;EAChC,MAAM,MAAM,MAAM,IAAI,OAAO;EAE7B,OAAO;GACL,GAAG,KAAK;GACR;GACA,mBAAmB,KAAK;GACxB,OAAO,SAAS;GAChB;GACA,oBAAoB,KAAK;EAC3B;CACF;CAEA,QAAqB;EACnB,OAAO,gBAAgB,SAAS,gBAAgB,OAAO,IAAI,GAAG,KAAK,WAAkC;CACvG;;;;CAKA,IAAW,UAAkB;EAC3B,OAAO,KAAK,oBAAoB,EAAE,CAAC;CACrC;AACF;AA9GE,cAAuB,OAAO"}