diff --git a/cloud/src/Ingest/EventValidator.php b/cloud/src/Ingest/EventValidator.php index a119935..9f26d07 100644 --- a/cloud/src/Ingest/EventValidator.php +++ b/cloud/src/Ingest/EventValidator.php @@ -22,6 +22,16 @@ final class EventValidator elseif (count($snaps) > 3) $errors[] = 'too_many:snapshots'; else foreach ($snaps as $s) if (!is_string($s)) { $errors[] = 'bad:snapshot_item'; break; } + // Type guards for required fields + if (!is_string($p['device_id'])) $errors[] = 'bad:device_id'; + if (!is_string($p['camera_id'])) $errors[] = 'bad:camera_id'; + if (!is_numeric($p['occurred_at'])) $errors[] = 'bad:occurred_at'; + + // Type guards for optional fields + if (isset($p['track_id']) && !is_numeric($p['track_id'])) $errors[] = 'bad:track_id'; + if (isset($p['zone_id']) && !is_string($p['zone_id'])) $errors[] = 'bad:zone_id'; + if (isset($p['duration_s']) && !is_numeric($p['duration_s'])) $errors[] = 'bad:duration_s'; + if ($errors) return ['ok' => false, 'errors' => $errors, 'clean' => []]; $clean = [ diff --git a/cloud/tests/EventValidatorTest.php b/cloud/tests/EventValidatorTest.php index 0bcfcca..d1612d3 100644 --- a/cloud/tests/EventValidatorTest.php +++ b/cloud/tests/EventValidatorTest.php @@ -31,4 +31,24 @@ final class EventValidatorTest extends TestCase $p = $this->valid(); $p['snapshots'] = ['a', 'b', 'c', 'd']; $this->assertFalse(EventValidator::validate($p)['ok']); } + public function testRejectsNonNumericOccurredAt(): void { + $p = $this->valid(); $p['occurred_at'] = ['bad']; + $this->assertFalse(EventValidator::validate($p)['ok']); + } + public function testRejectsNonStringDeviceId(): void { + $p = $this->valid(); $p['device_id'] = ['x']; + $this->assertFalse(EventValidator::validate($p)['ok']); + } + public function testRejectsNonArraySnapshots(): void { + $p = $this->valid(); $p['snapshots'] = 'notarray'; + $this->assertFalse(EventValidator::validate($p)['ok']); + } + public function testRejectsNonStringSnapshotItem(): void { + $p = $this->valid(); $p['snapshots'] = [123]; + $this->assertFalse(EventValidator::validate($p)['ok']); + } + public function testRejectsNonStringZoneId(): void { + $p = $this->valid(); $p['zone_id'] = ['z']; + $this->assertFalse(EventValidator::validate($p)['ok']); + } }