feat: Vendor-level consent + Consent analytics (F4 + F6)
F4: Granular Vendor-Level Consent - Migration 113: vendor_consents JSONB on banner_consents + audit_log - ConsentCreate schema + BannerConsentDB model extended - banner_consent_service stores vendor_consents alongside categories - Audit trail includes vendor-level decisions + user_agent F6: Consent Rate Analytics - Migration 114: user_agent on audit_log + time-series index - BannerAnalyticsService: time series, category breakdown, device stats - banner_analytics_routes: 4 endpoints (overview, time-series, categories, devices) - AnalyticsDashboard.tsx: KPIs, bar chart, category bars, device breakdown - New "Analytik" tab in cookie-banner page [migration-approved] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,6 +73,8 @@ class BannerConsentService:
|
||||
ip_hash: Optional[str] = None,
|
||||
banner_config_hash: Optional[str] = None,
|
||||
consent_version: Optional[int] = None,
|
||||
vendor_consents: Optional[dict[str, bool]] = None,
|
||||
user_agent: Optional[str] = None,
|
||||
) -> None:
|
||||
entry = BannerConsentAuditLogDB(
|
||||
tenant_id=tenant_id,
|
||||
@@ -81,7 +83,9 @@ class BannerConsentService:
|
||||
site_id=site_id,
|
||||
device_fingerprint=device_fingerprint,
|
||||
categories=categories or [],
|
||||
vendor_consents=vendor_consents or {},
|
||||
ip_hash=ip_hash,
|
||||
user_agent=user_agent,
|
||||
banner_config_hash=banner_config_hash,
|
||||
consent_version=consent_version,
|
||||
)
|
||||
@@ -143,6 +147,7 @@ class BannerConsentService:
|
||||
ip_address: Optional[str],
|
||||
user_agent: Optional[str],
|
||||
consent_string: Optional[str],
|
||||
vendor_consents: Optional[dict[str, bool]] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""Upsert a device consent row for (tenant, site, device_fingerprint).
|
||||
|
||||
@@ -171,6 +176,7 @@ class BannerConsentService:
|
||||
if existing:
|
||||
existing.categories = categories
|
||||
existing.vendors = vendors
|
||||
existing.vendor_consents = vendor_consents or {}
|
||||
existing.ip_hash = ip_hash
|
||||
existing.user_agent = user_agent
|
||||
existing.consent_string = consent_string
|
||||
@@ -180,6 +186,7 @@ class BannerConsentService:
|
||||
self._log(
|
||||
tid, existing.id, "consent_updated", site_id, device_fingerprint,
|
||||
categories, ip_hash, config_hash, config_ver,
|
||||
vendor_consents=vendor_consents, user_agent=user_agent,
|
||||
)
|
||||
self.db.commit()
|
||||
self.db.refresh(existing)
|
||||
@@ -191,6 +198,7 @@ class BannerConsentService:
|
||||
device_fingerprint=device_fingerprint,
|
||||
categories=categories,
|
||||
vendors=vendors,
|
||||
vendor_consents=vendor_consents or {},
|
||||
ip_hash=ip_hash,
|
||||
user_agent=user_agent,
|
||||
consent_string=consent_string,
|
||||
@@ -201,6 +209,7 @@ class BannerConsentService:
|
||||
self._log(
|
||||
tid, consent.id, "consent_given", site_id, device_fingerprint,
|
||||
categories, ip_hash, config_hash, config_ver,
|
||||
vendor_consents=vendor_consents, user_agent=user_agent,
|
||||
)
|
||||
self.db.commit()
|
||||
self.db.refresh(consent)
|
||||
|
||||
Reference in New Issue
Block a user