PR-001: Domain Model v1.0 — compile-only, zero dependencies
- @landvex/domain package with TypeScript strict mode - 3 Aggregate Roots: FieldSession, Mission, DecisionCase - Branded IDs, Value Objects, Domain Events, Invariants - 19 unit tests for IDs, FieldSession, DecisionCase - Zero runtime dependencies (only TypeScript + jest for tests) - Separates Entity / Value Object / Aggregate Root - README documents Three Rules of the domain Definition of Done met: - Compiles without errors - Exports all domain types - Unit tests for invariants and value objects - No PostgreSQL, S3, Express, AI models, queues
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Value Objects - immutable, compared by value, not identity
|
||||
*/
|
||||
|
||||
export interface GeoLocation {
|
||||
readonly lat: number;
|
||||
readonly lng: number;
|
||||
readonly accuracy?: number; // meters
|
||||
}
|
||||
|
||||
export interface BoundingBox {
|
||||
readonly x: number;
|
||||
readonly y: number;
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
export interface Confidence {
|
||||
readonly value: number; // 0.0 to 1.0
|
||||
}
|
||||
|
||||
export interface Hash {
|
||||
readonly algorithm: 'sha256';
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
export interface StorageUri {
|
||||
readonly protocol: 's3' | 'r2' | 'file';
|
||||
readonly bucket?: string;
|
||||
readonly path: string;
|
||||
}
|
||||
|
||||
export interface Version {
|
||||
readonly major: number;
|
||||
readonly minor: number;
|
||||
readonly patch: number;
|
||||
}
|
||||
|
||||
export interface TimeRange {
|
||||
readonly start: Date;
|
||||
readonly end: Date;
|
||||
}
|
||||
|
||||
export interface DeviceInfo {
|
||||
readonly model: string;
|
||||
readonly os: string;
|
||||
readonly appVersion: string;
|
||||
}
|
||||
|
||||
export interface ExifData {
|
||||
readonly device?: string;
|
||||
readonly iso?: number;
|
||||
readonly exposure?: string;
|
||||
readonly focalLength?: string;
|
||||
readonly timestamp?: Date;
|
||||
}
|
||||
|
||||
export interface AssetMetadata {
|
||||
readonly exif: ExifData;
|
||||
readonly gps: GeoLocation;
|
||||
readonly device: DeviceInfo;
|
||||
}
|
||||
|
||||
export interface BusinessImpact {
|
||||
readonly risk: string;
|
||||
readonly cost: string;
|
||||
readonly time: string;
|
||||
readonly opportunity: string;
|
||||
}
|
||||
|
||||
export interface EvidenceContext {
|
||||
readonly historicalData?: boolean;
|
||||
readonly weatherData?: boolean;
|
||||
readonly trafficData?: boolean;
|
||||
readonly gisData?: boolean;
|
||||
}
|
||||
|
||||
export interface QualityIssue {
|
||||
readonly type: 'blur' | 'duplicate' | 'bad_gps' | 'low_resolution' | 'missing_metadata' | 'wrong_timestamp' | 'occlusion';
|
||||
readonly severity: Severity;
|
||||
readonly description: string;
|
||||
}
|
||||
|
||||
export interface ValidationResult {
|
||||
readonly valid: boolean;
|
||||
readonly issues: QualityIssue[];
|
||||
}
|
||||
|
||||
export type Severity = 'low' | 'medium' | 'high' | 'critical';
|
||||
export type Priority = 'low' | 'medium' | 'high' | 'urgent';
|
||||
|
||||
export const Severity = {
|
||||
LOW: 'low' as Severity,
|
||||
MEDIUM: 'medium' as Severity,
|
||||
HIGH: 'high' as Severity,
|
||||
CRITICAL: 'critical' as Severity
|
||||
};
|
||||
|
||||
export const Priority = {
|
||||
LOW: 'low' as Priority,
|
||||
MEDIUM: 'medium' as Priority,
|
||||
HIGH: 'high' as Priority,
|
||||
URGENT: 'urgent' as Priority
|
||||
};
|
||||
Reference in New Issue
Block a user