export class CameraSession { constructor({ enabled = false, grantMinutes = 3, device = '', clock = () => Date.now(), audit } = {}) { this.clock = clock; this.enabled = Boolean(enabled); this.grantMinutes = Math.min(15, Math.max(1, Number(grantMinutes) || 3)); this.device = String(device || ''); this.active = false; this.expiresAt = null; this.backend = 'none'; this.audit = audit; } grant() { this.active = true; this.expiresAt = this.clock() + this.grantMinutes * 60 * 1000; return { active: true, grant_expires_at: this.expiresAt, device: this.device }; } setBackend(backend) { this.backend = ['portal', 'v4l2', 'grant', 'none'].includes(backend) ? backend : 'none'; return this.backend; } revoke() { this.active = false; this.expiresAt = null; this.backend = 'none'; Promise.resolve(this.audit?.wipeTemp?.('/tmp/jarvis-webcam')).catch(() => {}); } status() { if (this.active && this.expiresAt != null && this.clock() >= this.expiresAt) this.revoke(); return { enabled: this.enabled, active: this.active, device: this.device, grant_expires_at: this.expiresAt, backend: this.backend, }; } assertActive() { if (!this.active) throw new Error('webcam grant is inactive'); if (this.expiresAt && this.clock() >= this.expiresAt) { this.revoke(); throw new Error('webcam grant expired'); } } }