import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn, Index, } from 'typeorm'; import { Device } from './device.entity'; export enum CertificateStatus { ACTIVE = 'active', REVOKED = 'revoked', EXPIRED = 'expired', PENDING = 'pending', } export enum CertificateType { DEVICE = 'device', USER = 'user', INTERMEDIATE = 'intermediate', ROOT = 'root', } @Entity('device_certificates') @Index(['deviceId']) @Index(['status']) @Index(['expiresAt']) @Index(['serialNumber'], { unique: true }) @Index(['fingerprint'], { unique: true }) export class DeviceCertificate { @PrimaryGeneratedColumn('uuid') id: string; @Column({ name: 'device_id' }) deviceId: string; @ManyToOne(() => Device, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'device_id' }) device: Device; @Column({ name: 'serial_number', type: 'varchar', length: 100, unique: true }) serialNumber: string; @Column({ name: 'fingerprint', type: 'varchar', length: 128, unique: true }) fingerprint: string; @Column({ name: 'certificate_type', type: 'enum', enum: CertificateType, default: CertificateType.DEVICE, }) certificateType: CertificateType; @Column({ name: 'status', type: 'enum', enum: CertificateStatus, default: CertificateStatus.ACTIVE, }) status: CertificateStatus; @Column({ name: 'subject_dn', type: 'text' }) subjectDn: string; @Column({ name: 'issuer_dn', type: 'text' }) issuerDn: string; @Column({ name: 'certificate_pem', type: 'text' }) certificatePem: string; @Column({ name: 'private_key_pem', type: 'text', nullable: true }) privateKeyPem?: string; @Column({ name: 'public_key_pem', type: 'text' }) publicKeyPem: string; @Column({ name: 'key_algorithm', type: 'varchar', length: 50 }) keyAlgorithm: string; @Column({ name: 'key_size', type: 'int' }) keySize: number; @Column({ name: 'signature_algorithm', type: 'varchar', length: 50 }) signatureAlgorithm: string; @Column({ name: 'issued_at', type: 'timestamptz' }) issuedAt: Date; @Column({ name: 'expires_at', type: 'timestamptz' }) expiresAt: Date; @Column({ name: 'revoked_at', type: 'timestamptz', nullable: true }) revokedAt?: Date; @Column({ name: 'revocation_reason', type: 'varchar', length: 100, nullable: true }) revocationReason?: string; @Column({ name: 'x509_extensions', type: 'jsonb', nullable: true }) x509Extensions?: { key_usage: string[]; extended_key_usage: string[]; subject_alt_name?: string[]; basic_constraints?: { ca: boolean; path_len_constraint?: number; }; authority_key_identifier?: string; subject_key_identifier?: string; }; @Column({ name: 'usage_count', type: 'bigint', default: 0 }) usageCount: number; @Column({ name: 'last_used_at', type: 'timestamptz', nullable: true }) lastUsedAt?: Date; @Column({ name: 'renewal_notified_at', type: 'timestamptz', nullable: true }) renewalNotifiedAt?: Date; @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) createdAt: Date; @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) updatedAt: Date; }