458 lines
10 KiB
TypeScript
458 lines
10 KiB
TypeScript
/**
|
|
* @file lifecycle.ts
|
|
* @description Document lifecycle and audit interfaces
|
|
* Status workflow, transitions, retention policies, and legal holds
|
|
*/
|
|
|
|
import * as plugins from './plugins.js';
|
|
import type {
|
|
TContractStatus,
|
|
TTerminationReason,
|
|
TActionCategory,
|
|
TActionSeverity,
|
|
TPaymentFrequency,
|
|
} from './types.js';
|
|
import type { IDuration, IMonetaryAmount, IPriceAdjustment } from './terms.js';
|
|
|
|
// ============================================================================
|
|
// STATUS TRANSITIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Validation check for status transition
|
|
*/
|
|
export interface IStatusValidation {
|
|
rule: string;
|
|
description: string;
|
|
passed: boolean;
|
|
failureReason?: string;
|
|
checkedAt: number;
|
|
}
|
|
|
|
/**
|
|
* Status transition with validation
|
|
*/
|
|
export interface IStatusTransition {
|
|
fromStatus: TContractStatus;
|
|
toStatus: TContractStatus;
|
|
triggeredBy: string;
|
|
triggeredAt: number;
|
|
reason?: string;
|
|
metadata?: Record<string, unknown>;
|
|
validationsPerformed: IStatusValidation[];
|
|
}
|
|
|
|
/**
|
|
* Validation rule for transitions
|
|
*/
|
|
export interface ITransitionValidationRule {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
validatorType: 'signature_count' | 'approval_chain' | 'date_check' | 'custom';
|
|
parameters?: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* Status transition rules configuration
|
|
*/
|
|
export interface IStatusTransitionRule {
|
|
allowedTransitions: TContractStatus[];
|
|
requiredValidations: ITransitionValidationRule[];
|
|
requiresApproval: boolean;
|
|
approverRoles?: string[];
|
|
}
|
|
|
|
/**
|
|
* Map of status transition rules
|
|
*/
|
|
export type TStatusTransitionRules = Record<TContractStatus, IStatusTransitionRule>;
|
|
|
|
// ============================================================================
|
|
// TERMINATION
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Early termination penalty
|
|
*/
|
|
export interface IEarlyTerminationPenalty {
|
|
amount: number;
|
|
currency: string;
|
|
paid: boolean;
|
|
paidAt?: number;
|
|
}
|
|
|
|
/**
|
|
* Termination record
|
|
*/
|
|
export interface ITermination {
|
|
terminatedAt: number;
|
|
terminatedBy: string;
|
|
effectiveDate: number;
|
|
reason: TTerminationReason;
|
|
customReasonDescription?: string;
|
|
noticeGiven: boolean;
|
|
noticeDate?: number;
|
|
noticePeriodDays?: number;
|
|
earlyTerminationPenalty?: IEarlyTerminationPenalty;
|
|
mutuallyAgreed: boolean;
|
|
agreementDocumentId?: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// EXPIRATION AND RENEWAL
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Auto-renewal terms
|
|
*/
|
|
export interface IAutoRenewTerms {
|
|
renewalPeriodMonths: number;
|
|
maxRenewals: number;
|
|
currentRenewalCount: number;
|
|
priceAdjustment?: IPriceAdjustment;
|
|
}
|
|
|
|
/**
|
|
* Renewal notice information
|
|
*/
|
|
export interface IRenewalNotice {
|
|
requiredNoticeDays: number;
|
|
noticeReceivedAt?: number;
|
|
renewalDeclined: boolean;
|
|
declinedAt?: number;
|
|
declinedBy?: string;
|
|
}
|
|
|
|
/**
|
|
* Expiration and renewal handling
|
|
*/
|
|
export interface IExpirationConfig {
|
|
expirationDate: number;
|
|
reminderDays: number[];
|
|
autoRenew: boolean;
|
|
autoRenewTerms?: IAutoRenewTerms;
|
|
renewalNotice?: IRenewalNotice;
|
|
}
|
|
|
|
// ============================================================================
|
|
// STATUS HISTORY
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Complete status history entry
|
|
*/
|
|
export interface IStatusHistoryEntry {
|
|
id: string;
|
|
previousStatus: TContractStatus | null;
|
|
newStatus: TContractStatus;
|
|
transition: IStatusTransition;
|
|
versionIdAtTransition: string;
|
|
hashChainLink: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// DOCUMENT LIFECYCLE
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Document lifecycle state
|
|
*/
|
|
export interface IDocumentLifecycle {
|
|
contractId: string;
|
|
currentStatus: TContractStatus;
|
|
statusHistory: IStatusHistoryEntry[];
|
|
createdAt: number;
|
|
firstPublishedAt?: number;
|
|
executedAt?: number;
|
|
effectiveDate?: number;
|
|
expiration?: IExpirationConfig;
|
|
termination?: ITermination;
|
|
supersededBy?: string;
|
|
supersedes?: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// AUDIT LOG
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Geolocation for audit entry
|
|
*/
|
|
export interface IAuditGeolocation {
|
|
country: string;
|
|
region?: string;
|
|
city?: string;
|
|
coordinates?: {
|
|
lat: number;
|
|
lng: number;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Digital signature for audit entry non-repudiation
|
|
*/
|
|
export interface IAuditDigitalSignature {
|
|
signedBy: string;
|
|
algorithm: 'RSA-SHA256' | 'ECDSA-P256';
|
|
signature: string;
|
|
certificate?: string;
|
|
}
|
|
|
|
/**
|
|
* Extended action interface building on IObjectAction from tsclass
|
|
*/
|
|
export interface IContractAction extends plugins.tsclass.database.IObjectAction {
|
|
id: string;
|
|
contractId: string;
|
|
versionId?: string;
|
|
category: TActionCategory;
|
|
severity: TActionSeverity;
|
|
ipAddress?: string;
|
|
userAgent?: string;
|
|
sessionId?: string;
|
|
location?: IAuditGeolocation;
|
|
previousActionHash: string;
|
|
actionHash: string;
|
|
digitalSignature?: IAuditDigitalSignature;
|
|
}
|
|
|
|
/**
|
|
* Audit log statistics
|
|
*/
|
|
export interface IAuditStatistics {
|
|
totalActions: number;
|
|
actionsByCategory: Record<TActionCategory, number>;
|
|
uniqueUsers: string[];
|
|
dateRange: {
|
|
earliest: number;
|
|
latest: number;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Complete audit log for a contract
|
|
*/
|
|
export interface IAuditLog {
|
|
contractId: string;
|
|
actions: IContractAction[];
|
|
genesisHash: string;
|
|
currentHash: string;
|
|
chainLength: number;
|
|
lastVerifiedAt?: number;
|
|
statistics: IAuditStatistics;
|
|
}
|
|
|
|
// ============================================================================
|
|
// RETENTION AND LEGAL HOLDS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Retention policy scope
|
|
*/
|
|
export interface IRetentionScope {
|
|
contractTypes?: string[];
|
|
jurisdictions?: string[];
|
|
tags?: string[];
|
|
allContracts?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Retention period configuration
|
|
*/
|
|
export interface IRetentionPeriod {
|
|
duration: number;
|
|
startFrom: 'execution' | 'expiration' | 'termination' | 'creation';
|
|
}
|
|
|
|
/**
|
|
* Retention policy configuration
|
|
*/
|
|
export interface IRetentionPolicy {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
appliesTo: IRetentionScope;
|
|
retentionPeriod: IRetentionPeriod;
|
|
endOfRetentionAction: 'archive' | 'delete' | 'review' | 'anonymize';
|
|
legalBasis?: string;
|
|
legalHoldOverrides: boolean;
|
|
}
|
|
|
|
/**
|
|
* Legal hold for litigation/investigation
|
|
*/
|
|
export interface ILegalHold {
|
|
id: string;
|
|
name: string;
|
|
description: string;
|
|
contractIds: string[];
|
|
userIds?: string[];
|
|
dateRange?: {
|
|
start: number;
|
|
end: number;
|
|
};
|
|
createdBy: string;
|
|
createdAt: number;
|
|
reason: string;
|
|
caseReference?: string;
|
|
indefinite: boolean;
|
|
expiresAt?: number;
|
|
status: 'active' | 'released' | 'expired';
|
|
releasedBy?: string;
|
|
releasedAt?: number;
|
|
releaseReason?: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// DISCOVERY EXPORT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Discovery export access log entry
|
|
*/
|
|
export interface IDiscoveryAccessLog {
|
|
userId: string;
|
|
accessedAt: number;
|
|
action: 'download' | 'view';
|
|
ipAddress: string;
|
|
}
|
|
|
|
/**
|
|
* Export package for legal discovery
|
|
*/
|
|
export interface IDiscoveryExport {
|
|
id: string;
|
|
requestedBy: string;
|
|
requestedAt: number;
|
|
contractIds: string[];
|
|
dateRange?: {
|
|
start: number;
|
|
end: number;
|
|
};
|
|
includeAuditLog: boolean;
|
|
includeVersionHistory: boolean;
|
|
includeComments: boolean;
|
|
includeAttachments: boolean;
|
|
format: 'pdf' | 'json' | 'xml' | 'native';
|
|
packageUrl?: string;
|
|
packageHash?: string;
|
|
generatedAt?: number;
|
|
expiresAt?: number;
|
|
accessLog: IDiscoveryAccessLog[];
|
|
}
|
|
|
|
// ============================================================================
|
|
// COMPLIANCE CHECK
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Individual compliance finding
|
|
*/
|
|
export interface IComplianceFinding {
|
|
id: string;
|
|
severity: 'critical' | 'major' | 'minor' | 'informational';
|
|
title: string;
|
|
description: string;
|
|
affectedElements?: string[];
|
|
recommendation?: string;
|
|
}
|
|
|
|
/**
|
|
* Compliance check result
|
|
*/
|
|
export interface IComplianceCheck {
|
|
checkId: string;
|
|
contractId: string;
|
|
performedAt: number;
|
|
performedBy: string;
|
|
checkType: 'retention' | 'signature_validity' | 'chain_integrity' | 'access_audit';
|
|
passed: boolean;
|
|
findings: IComplianceFinding[];
|
|
remediationRequired: boolean;
|
|
remediationActions?: string[];
|
|
remediationDeadline?: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// FACTORY FUNCTIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Create initial document lifecycle
|
|
*/
|
|
export function createInitialLifecycle(contractId: string): IDocumentLifecycle {
|
|
const now = Date.now();
|
|
return {
|
|
contractId,
|
|
currentStatus: 'draft',
|
|
statusHistory: [],
|
|
createdAt: now,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create empty audit log
|
|
*/
|
|
export function createEmptyAuditLog(contractId: string): IAuditLog {
|
|
const genesisHash = crypto.randomUUID();
|
|
return {
|
|
contractId,
|
|
actions: [],
|
|
genesisHash,
|
|
currentHash: genesisHash,
|
|
chainLength: 0,
|
|
statistics: {
|
|
totalActions: 0,
|
|
actionsByCategory: {} as Record<TActionCategory, number>,
|
|
uniqueUsers: [],
|
|
dateRange: {
|
|
earliest: 0,
|
|
latest: 0,
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a status transition
|
|
*/
|
|
export function createStatusTransition(
|
|
fromStatus: TContractStatus,
|
|
toStatus: TContractStatus,
|
|
triggeredBy: string,
|
|
reason?: string
|
|
): IStatusTransition {
|
|
return {
|
|
fromStatus,
|
|
toStatus,
|
|
triggeredBy,
|
|
triggeredAt: Date.now(),
|
|
reason,
|
|
validationsPerformed: [],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a legal hold
|
|
*/
|
|
export function createLegalHold(
|
|
name: string,
|
|
description: string,
|
|
contractIds: string[],
|
|
createdBy: string,
|
|
reason: string
|
|
): ILegalHold {
|
|
return {
|
|
id: crypto.randomUUID(),
|
|
name,
|
|
description,
|
|
contractIds,
|
|
createdBy,
|
|
createdAt: Date.now(),
|
|
reason,
|
|
indefinite: true,
|
|
status: 'active',
|
|
};
|
|
}
|