Spaces:
Running
Running
| from datetime import datetime, timedelta, timezone | |
| from typing import Literal | |
| from pydantic import BaseModel, Field | |
| class LoginRequest(BaseModel): | |
| username: str | |
| password: str | |
| class LoginResponse(BaseModel): | |
| token: str | |
| role: Literal["admin", "sensitive_admin"] = "admin" | |
| expires_in_seconds: int = 3600 | |
| class RegisterDeviceRequest(BaseModel): | |
| device_id: str | |
| hostname: str | |
| os_version: str | |
| agent_version: str | |
| class RegisterDeviceResponse(BaseModel): | |
| registered: bool = True | |
| session_token: str | |
| class HeartbeatRequest(BaseModel): | |
| device_id: str | |
| active_restriction_window: bool | |
| uptime_seconds: int = 0 | |
| class HeartbeatResponse(BaseModel): | |
| accepted: bool = True | |
| server_time: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) | |
| class DeviceStatusRow(BaseModel): | |
| device_id: str | |
| hostname: str | |
| agent_version: str | |
| os_version: str | |
| last_heartbeat_at: datetime | None = None | |
| active_restriction_window: bool = False | |
| class DeviceStatusResponse(DeviceStatusRow): | |
| is_online: bool = False | |
| class TimeWindow(BaseModel): | |
| day_of_week: Literal["mon", "tue", "wed", "thu", "fri", "sat", "sun"] | |
| start: str = Field(description="HH:MM") | |
| end: str = Field(description="HH:MM") | |
| class DevicePolicy(BaseModel): | |
| blocked_executables: list[str] = [] | |
| blocked_domains: list[str] = [] | |
| restriction_windows: list[TimeWindow] = [] | |
| class UpdatePolicyRequest(BaseModel): | |
| device_id: str | |
| policy: DevicePolicy | |
| class ScreenshotIngestResponse(BaseModel): | |
| screenshot_id: str | |
| queued: bool = True | |
| class ViolationScreenshot(BaseModel): | |
| screenshot_id: str | |
| device_id: str | |
| timestamp: str | |
| filename: str | |
| created_at: str | |
| image_url: str | |
| confidence: float | |
| reason: str | |
| visibility_scope: Literal["admin", "sensitive_admin"] = "admin" | |
| ocr_urls: list[str] = [] | |
| class GameReviewItem(BaseModel): | |
| review_id: str | |
| screenshot_id: str | |
| device_id: str | |
| timestamp: str | |
| status: Literal["pending", "approved", "rejected"] | |
| reason: str | |
| ocr_urls: list[str] = [] | |
| created_at: datetime | |
| class GameReviewDecisionRequest(BaseModel): | |
| review_id: str | |
| approve_lock: bool | |
| class GameReviewDecisionResponse(BaseModel): | |
| updated: bool | |
| class KeyGenerateRequest(BaseModel): | |
| device_id: str | |
| class KeyGenerateResponse(BaseModel): | |
| device_id: str | |
| key: str | |
| expires_at: datetime | |
| class KeyValidateRequest(BaseModel): | |
| device_id: str | |
| key: str | |
| class KeyValidateResponse(BaseModel): | |
| valid: bool | |
| lock_until: datetime | None = None | |
| class AlertEvent(BaseModel): | |
| device_id: str | |
| type: Literal[ | |
| "wrong_key", | |
| "policy_violation", | |
| "process_killed", | |
| "info", | |
| "device_status", | |
| "sensitive_detected", | |
| "game_lock_review_required", | |
| "game_lock_review_decision", | |
| ] | |
| message: str | |
| created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) | |
| def lock_until_5_minutes() -> datetime: | |
| return datetime.now(timezone.utc) + timedelta(minutes=5) | |