export const FIELDLENS_SCHEMA_VERSION = 1 as const export type SchemaVersion = typeof FIELDLENS_SCHEMA_VERSION export type ScanRecord = { id: string rawValue: string format: string duplicate: boolean capturedAt: string schemaVersion: SchemaVersion source?: 'camera' | 'print' | string sourceMetadata?: Record } export type PalletSession = { id: string workflowType: 'ean' | 'carton-label' targetCount: number startedAt: string completedAt?: string status: 'active' | 'complete' conforms?: boolean resultStatus?: 'pass' | 'fail' | 'review' schemaVersion: SchemaVersion } export type PalletObservation = { id: string palletSessionId: string cartonIndex: number ean?: string fieldsJson?: Record rawText?: string confidence?: number capturedAt: string schemaVersion: SchemaVersion } export type PalletException = { id: string palletSessionId: string observationId?: string field: string expectedValue?: string actualValue?: string exceptionType: string schemaVersion: SchemaVersion } export type OutboxEvent = { id: string aggregateId: string eventType: | 'scan.captured' | 'pallet.session.started' | 'pallet.observation.captured' | 'pallet.session.completed' schemaVersion: SchemaVersion payload: unknown createdAt: string } export type DeviceRegistration = { installationId: string stationId?: string label?: string appVersion?: string schemaVersion: SchemaVersion } export type Station = { id: string siteId: string name: string stationType: string active: boolean } export type SyncRequest = { deviceId: string schemaVersion: SchemaVersion events: OutboxEvent[] } export type SyncAcknowledgement = { eventId: string status: 'accepted' | 'duplicate' | 'rejected' error?: string } export type SyncResponse = { schemaVersion: SchemaVersion acknowledgements: SyncAcknowledgement[] } function isObject(value: unknown): value is Record { return typeof value === 'object' && value !== null && !Array.isArray(value) } export function isOutboxEvent(value: unknown): value is OutboxEvent { if (!isObject(value)) return false return typeof value.id === 'string' && typeof value.aggregateId === 'string' && typeof value.eventType === 'string' && value.schemaVersion === FIELDLENS_SCHEMA_VERSION && typeof value.createdAt === 'string' && 'payload' in value } export function isSyncRequest(value: unknown): value is SyncRequest { if (!isObject(value)) return false return typeof value.deviceId === 'string' && value.schemaVersion === FIELDLENS_SCHEMA_VERSION && Array.isArray(value.events) && value.events.length <= 100 && value.events.every(isOutboxEvent) }