ConsentOS — a privacy-first cookie consent management platform. Self-hosted, source-available alternative to OneTrust, Cookiebot, and CookieYes. Full standards coverage (IAB TCF v2.2, GPP v1, Google Consent Mode v2, GPC, Shopify Customer Privacy API), multi-tenant architecture with role-based access, configuration cascade (system → org → group → site → region), dark-pattern detection in the scanner, and a tamper-evident consent record audit trail. This is the initial public release. Prior development history is retained internally. See README.md for the feature list, architecture overview, and quick-start instructions. Licensed under the Elastic Licence 2.0 — self-host freely; do not resell as a managed service.
143 lines
3.7 KiB
Python
143 lines
3.7 KiB
Python
"""Pydantic schemas for scanner and client-side cookie reports."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from enum import StrEnum
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ScanStatus(StrEnum):
|
|
PENDING = "pending"
|
|
RUNNING = "running"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
|
|
|
|
class ScanTrigger(StrEnum):
|
|
MANUAL = "manual"
|
|
SCHEDULED = "scheduled"
|
|
CLIENT_REPORT = "client_report"
|
|
|
|
|
|
# ── Client-side cookie report ────────────────────────────────────────
|
|
|
|
|
|
class ReportedCookie(BaseModel):
|
|
"""A single cookie/storage item reported by the client-side reporter."""
|
|
|
|
name: str = Field(..., min_length=1, max_length=255)
|
|
domain: str = Field(..., min_length=1, max_length=255)
|
|
storage_type: str = Field(default="cookie", max_length=30)
|
|
value_length: int = Field(default=0, ge=0)
|
|
path: str | None = None
|
|
is_secure: bool | None = None
|
|
same_site: str | None = None
|
|
script_source: str | None = None
|
|
|
|
|
|
class CookieReportRequest(BaseModel):
|
|
"""Payload from the client-side cookie reporter."""
|
|
|
|
site_id: uuid.UUID
|
|
page_url: str = Field(..., max_length=2000)
|
|
cookies: list[ReportedCookie] = Field(..., max_length=500)
|
|
collected_at: datetime
|
|
user_agent: str = Field(default="", max_length=500)
|
|
|
|
|
|
class CookieReportResponse(BaseModel):
|
|
"""Acknowledgement response for a cookie report."""
|
|
|
|
accepted: bool = True
|
|
cookies_received: int
|
|
new_cookies: int = 0
|
|
|
|
|
|
# ── Scan job schemas ─────────────────────────────────────────────────
|
|
|
|
|
|
class ScanResultResponse(BaseModel):
|
|
"""A single scan result — a cookie found on a specific page."""
|
|
|
|
id: uuid.UUID
|
|
scan_job_id: uuid.UUID
|
|
page_url: str
|
|
cookie_name: str
|
|
cookie_domain: str
|
|
storage_type: str
|
|
attributes: dict | None = None
|
|
script_source: str | None = None
|
|
auto_category: str | None = None
|
|
initiator_chain: list[str] | None = None
|
|
found_at: datetime
|
|
created_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class ScanJobResponse(BaseModel):
|
|
"""Response schema for a scan job."""
|
|
|
|
id: uuid.UUID
|
|
site_id: uuid.UUID
|
|
status: str
|
|
trigger: str
|
|
pages_scanned: int
|
|
pages_total: int | None
|
|
cookies_found: int
|
|
error_message: str | None
|
|
started_at: datetime | None
|
|
completed_at: datetime | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class ScanJobDetailResponse(ScanJobResponse):
|
|
"""Scan job with results included."""
|
|
|
|
results: list[ScanResultResponse] = []
|
|
|
|
|
|
class TriggerScanRequest(BaseModel):
|
|
"""Request to trigger a new scan."""
|
|
|
|
site_id: uuid.UUID
|
|
max_pages: int = Field(default=50, ge=1, le=500)
|
|
|
|
|
|
# ── Diff engine schemas ──────────────────────────────────────────────
|
|
|
|
|
|
class DiffStatus(StrEnum):
|
|
NEW = "new"
|
|
REMOVED = "removed"
|
|
CHANGED = "changed"
|
|
|
|
|
|
class CookieDiffItem(BaseModel):
|
|
"""A single cookie difference between two scans."""
|
|
|
|
name: str
|
|
domain: str
|
|
storage_type: str
|
|
diff_status: DiffStatus
|
|
details: str | None = None
|
|
|
|
|
|
class ScanDiffResponse(BaseModel):
|
|
"""Diff between two scans."""
|
|
|
|
current_scan_id: uuid.UUID
|
|
previous_scan_id: uuid.UUID | None
|
|
new_cookies: list[CookieDiffItem] = []
|
|
removed_cookies: list[CookieDiffItem] = []
|
|
changed_cookies: list[CookieDiffItem] = []
|
|
total_new: int = 0
|
|
total_removed: int = 0
|
|
total_changed: int = 0
|