import { ApiPropertyOptional } from "@nestjs/swagger";
import { Type } from "class-transformer";
import {
IsArray,
IsBoolean,
IsEnum,
IsNumber,
IsObject,
IsOptional,
IsString,
ValidateIf,
ValidateNested,
} from "class-validator";
export enum IssuerRegistrationCertificateMode {
IMPORT = "import",
GENERATE = "generate",
}
export class IssuerProvidedAttestation {
@ApiPropertyOptional({
description:
"Attestation format as expected by the registrar (for example dc+sd-jwt, mso_mdoc).",
example: "dc+sd-jwt",
})
@IsOptional()
@IsString()
format?: string;
@ApiPropertyOptional({
description:
"Arbitrary attestation metadata forwarded to the registrar.",
type: "object",
additionalProperties: true,
})
@IsOptional()
@IsObject()
meta?: Record<string, unknown>;
}
export class IssuerRegistrationCertificateConfig {
@ApiPropertyOptional({
description:
"Enable inclusion of a registration certificate in credential issuer metadata.",
default: false,
})
@IsOptional()
@IsBoolean()
enabled?: boolean;
@ApiPropertyOptional({
enum: IssuerRegistrationCertificateMode,
description:
"import: use an existing JWT, generate: create via registrar from provided attestations and selected credential configurations.",
default: IssuerRegistrationCertificateMode.IMPORT,
})
@IsOptional()
@IsEnum(IssuerRegistrationCertificateMode)
mode?: IssuerRegistrationCertificateMode;
@ApiPropertyOptional({
description:
"Existing registration certificate JWT used when mode is import.",
})
@ValidateIf(
(value: IssuerRegistrationCertificateConfig) =>
value.mode === IssuerRegistrationCertificateMode.IMPORT,
)
@IsOptional()
@IsString()
jwt?: string;
@ApiPropertyOptional({
description:
"Schema metadata IDs selected for inclusion in generated registration certificates.",
type: () => [String],
})
@IsOptional()
@IsArray()
@IsString({ each: true })
schemaMetadataIds?: string[];
@ApiPropertyOptional({
description:
"Privacy policy URL used when generating a registration certificate (optional if registrar defaults are configured).",
example: "https://issuer.example/privacy",
})
@IsOptional()
@IsString()
privacyPolicy?: string;
@ApiPropertyOptional({
description:
"Support URI used when generating a registration certificate (optional if registrar defaults are configured).",
example: "mailto:support@issuer.example",
})
@IsOptional()
@IsString()
supportUri?: string;
@ApiPropertyOptional({
description:
"Provided attestations included in generated registration certificates.",
type: () => [IssuerProvidedAttestation],
})
@ValidateIf(
(value: IssuerRegistrationCertificateConfig) =>
value.mode === IssuerRegistrationCertificateMode.GENERATE,
)
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => IssuerProvidedAttestation)
providedAttestations?: IssuerProvidedAttestation[];
}
export class IssuerRegistrationCertificateCache {
@ApiPropertyOptional({
description:
"Cached registration certificate JWT generated by EUDIPLO.",
readOnly: true,
})
@IsString()
jwt!: string;
@ApiPropertyOptional({
description: "Config fingerprint used to detect cache invalidation.",
readOnly: true,
})
@IsString()
fingerprint!: string;
@ApiPropertyOptional({
description: "JWT iat claim, seconds since epoch.",
readOnly: true,
})
@IsOptional()
@IsNumber()
issuedAt?: number;
@ApiPropertyOptional({
description: "JWT exp claim, seconds since epoch.",
readOnly: true,
})
@IsOptional()
@IsNumber()
expiresAt?: number;
}