{"version":3,"file":"IssuerService.mjs","names":["IssuerService","repository: OpenBadgeCredentialRepository","proofs: ProofService","keys: KeyService","config: OpenBadgesModuleConfig","verificationMethod: string | undefined","uuidv4"],"sources":["../../src/services/IssuerService.ts"],"sourcesContent":["import type { AgentContext } from '@credo-ts/core'\nimport { injectable, inject } from '@credo-ts/core'\nimport { OpenBadgeCredentialRepository } from '../repository/OpenBadgeCredentialRepository'\nimport { OpenBadgeCredentialRecord } from '../repository/OpenBadgeCredentialRecord'\nimport { validateObEnvelope, validateEndorsementEnvelope } from '../utils/validate'\nimport type { EndorsementCredentialInput } from '../models/EndorsementCredential'\nimport type { ClrCredentialInput } from '../models/ClrCredential'\nimport { buildClrContexts, validateClrCredential } from '../models/ClrCredential'\nimport { CLR_V2_CONTEXT } from '../constants'\nimport { randomUUID as uuidv4 } from 'node:crypto'\nimport { ProofService } from './ProofService'\nimport { VC_V2_CONTEXT, OBV3_CONTEXT } from '../constants'\nimport { OpenBadgesModuleConfig } from '../OpenBadgesModuleConfig'\nimport { KeyService } from './KeyService'\n\n@injectable()\nexport class IssuerService {\n  public constructor(\n    @inject(OpenBadgeCredentialRepository) private readonly repository: OpenBadgeCredentialRepository,\n    @inject(ProofService) private readonly proofs: ProofService,\n    @inject(KeyService) private readonly keys: KeyService,\n    @inject(OpenBadgesModuleConfig) private readonly config: OpenBadgesModuleConfig\n  ) {}\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  public async issueCredential(agentContext: AgentContext, input: any) {\n    const logger = agentContext.config.logger\n    logger.debug('[OB] IssuerService.issueCredential() start')\n    // Ensure required contexts are present\n    const base = Array.isArray(input?.['@context']) ? input['@context'] : input?.['@context'] ? [input['@context']] : []\n    const withCtx = { ...input, '@context': Array.from(new Set([VC_V2_CONTEXT, OBV3_CONTEXT, ...base])) }\n    // Never pass an existing proof into the signer; suites will create the proof\n    const toSign = { ...withCtx }\n    try { delete (toSign as any).proof } catch {}\n\n    // Validate the envelope\n    const issues = validateObEnvelope(withCtx)\n    if (issues.length) {\n      logger.error('[OB] Invalid OBv3 envelope', { issues })\n      throw new Error(`Invalid OBv3 envelope: ${issues.map((i) => i.code).join(', ')}`)\n    }\n\n    // Resolve / ensure key binding for verificationMethod\n    const verificationMethod: string | undefined = input?.proof?.verificationMethod\n    logger.debug('[OB] verificationMethod provided', { verificationMethod })\n    if (!verificationMethod) {\n      logger.error('[OB] missing_verification_method_key')\n      throw new Error('missing_verification_method_key')\n    }\n    const controller = verificationMethod.split('#')[0]\n    try {\n      await this.keys.ensureBinding(agentContext, { controller, vmId: verificationMethod })\n    } catch (e) {\n      logger.warn('[OB] ensureBinding failed', { error: (e as any)?.message || String(e) })\n    }\n    const signed = await this.proofs.sign(agentContext, toSign, { id: verificationMethod, controller })\n\n    const record = new OpenBadgeCredentialRecord({\n      credential: signed,\n      derived: undefined,\n      status: 'unknown',\n    })\n\n    try {\n      await this.repository.save(agentContext, record)\n      logger.debug('[OB] Saved OpenBadgeCredentialRecord', { recordId: record.id })\n    } catch (e) {\n      logger.error('[OB] repository.save failed', { error: (e as any)?.message || String(e) })\n      throw e\n    }\n    return record\n  }\n\n  /**\n   * Issues an EndorsementCredential - a third-party validation credential\n   *\n   * EndorsementCredentials allow external organizations or individuals to\n   * endorse achievements, profiles, or other credentials.\n   *\n   * @param agentContext - The agent context\n   * @param input - The endorsement credential input\n   * @returns The saved credential record\n   */\n  public async issueEndorsement(agentContext: AgentContext, input: EndorsementCredentialInput) {\n    const logger = agentContext.config.logger\n    logger.debug('[OB] IssuerService.issueEndorsement() start')\n\n    // Build the endorsement credential structure\n    const credentialId = input.id || `urn:uuid:${uuidv4()}`\n    const validFrom = input.validFrom || new Date().toISOString()\n\n    const endorsementCredential = {\n      '@context': [VC_V2_CONTEXT, OBV3_CONTEXT],\n      type: ['VerifiableCredential', 'EndorsementCredential'] as const,\n      id: credentialId,\n      issuer: input.issuerProfile,\n      validFrom,\n      ...(input.validUntil && { validUntil: input.validUntil }),\n      credentialSubject: {\n        id: input.endorsedEntity,\n        type: 'EndorsementSubject' as const,\n        ...(input.endorsementComment && { endorsementComment: input.endorsementComment }),\n      },\n    }\n\n    // Validate the envelope\n    const issues = validateEndorsementEnvelope(endorsementCredential)\n    if (issues.length) {\n      logger.error('[OB] Invalid EndorsementCredential envelope', { issues })\n      throw new Error(`Invalid EndorsementCredential envelope: ${issues.map((i) => i.code).join(', ')}`)\n    }\n\n    // Resolve / ensure key binding for verificationMethod\n    const verificationMethod = input.verificationMethod\n    logger.debug('[OB] Endorsement verificationMethod provided', { verificationMethod })\n    if (!verificationMethod) {\n      logger.error('[OB] missing_verification_method_key')\n      throw new Error('missing_verification_method_key')\n    }\n\n    const controller = verificationMethod.split('#')[0]\n    try {\n      await this.keys.ensureBinding(agentContext, { controller, vmId: verificationMethod })\n    } catch (e) {\n      logger.warn('[OB] ensureBinding failed', { error: (e as any)?.message || String(e) })\n    }\n\n    const signed = await this.proofs.sign(agentContext, endorsementCredential, { id: verificationMethod, controller })\n\n    const record = new OpenBadgeCredentialRecord({\n      credential: signed,\n      derived: undefined,\n      status: 'unknown',\n    })\n\n    try {\n      await this.repository.save(agentContext, record)\n      logger.debug('[OB] Saved EndorsementCredential record', { recordId: record.id })\n    } catch (e) {\n      logger.error('[OB] repository.save failed', { error: (e as any)?.message || String(e) })\n      throw e\n    }\n\n    return record\n  }\n\n  /**\n   * Issues a ClrCredential - a Comprehensive Learner Record bundling multiple credentials\n   *\n   * CLR credentials allow bundling multiple OpenBadgeCredentials into a single\n   * verifiable credential representing a learner's complete achievement record.\n   *\n   * @param agentContext - The agent context\n   * @param input - The CLR credential input\n   * @returns The saved credential record\n   */\n  public async issueClr(agentContext: AgentContext, input: ClrCredentialInput) {\n    const logger = agentContext.config.logger\n    logger.debug('[OB] IssuerService.issueClr() start')\n\n    // Build the CLR credential structure\n    const credentialId = input.id || `urn:uuid:${uuidv4()}`\n    const validFrom = input.validFrom || new Date().toISOString()\n\n    const clrCredential = {\n      '@context': buildClrContexts(),\n      type: ['VerifiableCredential', 'ClrCredential'] as ['VerifiableCredential', 'ClrCredential'],\n      id: credentialId,\n      issuer: input.issuerProfile,\n      validFrom,\n      ...(input.validUntil && { validUntil: input.validUntil }),\n      ...(input.name && { name: input.name }),\n      ...(input.description && { description: input.description }),\n      credentialSubject: {\n        id: input.learnerId,\n        type: 'ClrSubject' as const,\n        verifiableCredential: input.verifiableCredentials,\n        ...(input.associations && input.associations.length > 0 && { association: input.associations }),\n      },\n    }\n\n    // Validate the CLR structure\n    const issues = validateClrCredential(clrCredential)\n    if (issues.length) {\n      logger.error('[OB] Invalid ClrCredential envelope', { issues })\n      throw new Error(`Invalid ClrCredential envelope: ${issues.join(', ')}`)\n    }\n\n    // Resolve / ensure key binding for verificationMethod\n    const verificationMethod = input.verificationMethod\n    logger.debug('[OB] CLR verificationMethod provided', { verificationMethod })\n    if (!verificationMethod) {\n      logger.error('[OB] missing_verification_method_key')\n      throw new Error('missing_verification_method_key')\n    }\n\n    const controller = verificationMethod.split('#')[0]\n    try {\n      await this.keys.ensureBinding(agentContext, { controller, vmId: verificationMethod })\n    } catch (e) {\n      logger.warn('[OB] ensureBinding failed', { error: (e as any)?.message || String(e) })\n    }\n\n    const signed = await this.proofs.sign(agentContext, clrCredential, { id: verificationMethod, controller })\n\n    const record = new OpenBadgeCredentialRecord({\n      credential: signed,\n      derived: undefined,\n      status: 'unknown',\n    })\n\n    try {\n      await this.repository.save(agentContext, record)\n      logger.debug('[OB] Saved ClrCredential record', { recordId: record.id })\n    } catch (e) {\n      logger.error('[OB] repository.save failed', { error: (e as any)?.message || String(e) })\n      throw e\n    }\n\n    return record\n  }\n}\n"],"mappings":"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"}