Install LOC guardrails (check-loc.sh, architecture.md, pre-commit hook) and split all 44 files exceeding 500 LOC into domain-focused modules: - consent-service (Go): models, handlers, services, database splits - backend-core (Python): security_api, rbac_api, pdf_service, auth splits - admin-core (TypeScript): 5 page.tsx + sidebar extractions - pitch-deck (TypeScript): 6 slides, 3 UI components, engine.ts splits - voice-service (Python): enhanced_task_orchestrator split Result: 0 violations, 36 exempted (pipeline, tests, pure-data files). Go build verified clean. No behavior changes — pure structural splits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
238 lines
10 KiB
Go
238 lines
10 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// LegalDocument represents a type of legal document (e.g., Terms, Privacy Policy)
|
|
type LegalDocument struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
Type string `json:"type" db:"type"` // 'terms', 'privacy', 'cookies', 'community'
|
|
Name string `json:"name" db:"name"`
|
|
Description *string `json:"description" db:"description"`
|
|
IsMandatory bool `json:"is_mandatory" db:"is_mandatory"`
|
|
IsActive bool `json:"is_active" db:"is_active"`
|
|
SortOrder int `json:"sort_order" db:"sort_order"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
// DocumentVersion represents a specific version of a legal document
|
|
type DocumentVersion struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
DocumentID uuid.UUID `json:"document_id" db:"document_id"`
|
|
Version string `json:"version" db:"version"` // Semver: 1.0.0, 1.1.0
|
|
Language string `json:"language" db:"language"` // ISO 639-1: de, en
|
|
Title string `json:"title" db:"title"`
|
|
Content string `json:"content" db:"content"` // HTML or Markdown
|
|
Summary *string `json:"summary" db:"summary"` // Summary of changes
|
|
Status string `json:"status" db:"status"` // 'draft', 'review', 'approved', 'scheduled', 'published', 'archived'
|
|
PublishedAt *time.Time `json:"published_at" db:"published_at"`
|
|
ScheduledPublishAt *time.Time `json:"scheduled_publish_at" db:"scheduled_publish_at"`
|
|
CreatedBy *uuid.UUID `json:"created_by" db:"created_by"`
|
|
ApprovedBy *uuid.UUID `json:"approved_by" db:"approved_by"`
|
|
ApprovedAt *time.Time `json:"approved_at" db:"approved_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
|
}
|
|
|
|
// UserConsent represents a user's consent to a document version
|
|
type UserConsent struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
DocumentVersionID uuid.UUID `json:"document_version_id" db:"document_version_id"`
|
|
Consented bool `json:"consented" db:"consented"`
|
|
IPAddress *string `json:"ip_address" db:"ip_address"`
|
|
UserAgent *string `json:"user_agent" db:"user_agent"`
|
|
ConsentedAt time.Time `json:"consented_at" db:"consented_at"`
|
|
WithdrawnAt *time.Time `json:"withdrawn_at" db:"withdrawn_at"`
|
|
}
|
|
|
|
// AuditLog represents an audit trail entry for GDPR compliance
|
|
type AuditLog struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID *uuid.UUID `json:"user_id" db:"user_id"`
|
|
Action string `json:"action" db:"action"` // 'consent_given', 'consent_withdrawn', 'data_export', 'data_delete'
|
|
EntityType *string `json:"entity_type" db:"entity_type"` // 'document', 'cookie_category'
|
|
EntityID *uuid.UUID `json:"entity_id" db:"entity_id"`
|
|
Details *string `json:"details" db:"details"` // JSON string
|
|
IPAddress *string `json:"ip_address" db:"ip_address"`
|
|
UserAgent *string `json:"user_agent" db:"user_agent"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// DataExportRequest represents a user's request to export their data
|
|
type DataExportRequest struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Status string `json:"status" db:"status"` // 'pending', 'processing', 'completed', 'failed'
|
|
DownloadURL *string `json:"download_url" db:"download_url"`
|
|
ExpiresAt *time.Time `json:"expires_at" db:"expires_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
CompletedAt *time.Time `json:"completed_at" db:"completed_at"`
|
|
}
|
|
|
|
// DataDeletionRequest represents a user's request to delete their data
|
|
type DataDeletionRequest struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Status string `json:"status" db:"status"` // 'pending', 'processing', 'completed', 'failed'
|
|
Reason *string `json:"reason" db:"reason"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
ProcessedAt *time.Time `json:"processed_at" db:"processed_at"`
|
|
ProcessedBy *uuid.UUID `json:"processed_by" db:"processed_by"`
|
|
}
|
|
|
|
// VersionApproval tracks the approval workflow
|
|
type VersionApproval struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
VersionID uuid.UUID `json:"version_id" db:"version_id"`
|
|
ApproverID uuid.UUID `json:"approver_id" db:"approver_id"`
|
|
Action string `json:"action" db:"action"` // 'submitted_for_review', 'approved', 'rejected', 'published'
|
|
Comment *string `json:"comment,omitempty" db:"comment"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// ConsentDeadline tracks consent deadlines per user
|
|
type ConsentDeadline struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
DocumentVersionID uuid.UUID `json:"document_version_id" db:"document_version_id"`
|
|
DeadlineAt time.Time `json:"deadline_at" db:"deadline_at"`
|
|
ReminderCount int `json:"reminder_count" db:"reminder_count"`
|
|
LastReminderAt *time.Time `json:"last_reminder_at,omitempty" db:"last_reminder_at"`
|
|
ConsentGivenAt *time.Time `json:"consent_given_at,omitempty" db:"consent_given_at"`
|
|
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
|
}
|
|
|
|
// AccountSuspension tracks account suspensions
|
|
type AccountSuspension struct {
|
|
ID uuid.UUID `json:"id" db:"id"`
|
|
UserID uuid.UUID `json:"user_id" db:"user_id"`
|
|
Reason string `json:"reason" db:"reason"` // 'consent_deadline_exceeded'
|
|
Details *string `json:"details,omitempty" db:"details"` // JSON
|
|
SuspendedAt time.Time `json:"suspended_at" db:"suspended_at"`
|
|
LiftedAt *time.Time `json:"lifted_at,omitempty" db:"lifted_at"`
|
|
LiftedReason *string `json:"lifted_reason,omitempty" db:"lifted_reason"`
|
|
}
|
|
|
|
// ========================================
|
|
// Consent DTOs
|
|
// ========================================
|
|
|
|
// CreateConsentRequest is the request body for creating a consent
|
|
type CreateConsentRequest struct {
|
|
DocumentType string `json:"document_type" binding:"required"`
|
|
VersionID string `json:"version_id" binding:"required"`
|
|
Consented bool `json:"consented"`
|
|
}
|
|
|
|
// ConsentCheckResponse is the response for checking consent status
|
|
type ConsentCheckResponse struct {
|
|
HasConsent bool `json:"has_consent"`
|
|
CurrentVersionID *string `json:"current_version_id,omitempty"`
|
|
ConsentedVersion *string `json:"consented_version,omitempty"`
|
|
NeedsUpdate bool `json:"needs_update"`
|
|
ConsentedAt *time.Time `json:"consented_at,omitempty"`
|
|
}
|
|
|
|
// DocumentWithVersion combines document info with its latest published version
|
|
type DocumentWithVersion struct {
|
|
Document LegalDocument `json:"document"`
|
|
LatestVersion *DocumentVersion `json:"latest_version,omitempty"`
|
|
}
|
|
|
|
// ConsentHistory represents a user's consent history for a document
|
|
type ConsentHistory struct {
|
|
Document LegalDocument `json:"document"`
|
|
Version DocumentVersion `json:"version"`
|
|
Consent UserConsent `json:"consent"`
|
|
}
|
|
|
|
// ConsentStats represents statistics about consents
|
|
type ConsentStats struct {
|
|
TotalUsers int `json:"total_users"`
|
|
ConsentedUsers int `json:"consented_users"`
|
|
ConsentRate float64 `json:"consent_rate"`
|
|
RecentConsents int `json:"recent_consents"` // Last 7 days
|
|
RecentWithdrawals int `json:"recent_withdrawals"`
|
|
}
|
|
|
|
// MyDataResponse represents all data we have about a user
|
|
type MyDataResponse struct {
|
|
User User `json:"user"`
|
|
Consents []ConsentHistory `json:"consents"`
|
|
CookieConsents []CookieConsent `json:"cookie_consents"`
|
|
AuditLog []AuditLog `json:"audit_log"`
|
|
ExportedAt time.Time `json:"exported_at"`
|
|
}
|
|
|
|
// CreateDocumentRequest is the request body for creating a document
|
|
type CreateDocumentRequest struct {
|
|
Type string `json:"type" binding:"required"`
|
|
Name string `json:"name" binding:"required"`
|
|
Description *string `json:"description"`
|
|
IsMandatory bool `json:"is_mandatory"`
|
|
}
|
|
|
|
// CreateVersionRequest is the request body for creating a document version
|
|
type CreateVersionRequest struct {
|
|
DocumentID string `json:"document_id" binding:"required"`
|
|
Version string `json:"version" binding:"required"`
|
|
Language string `json:"language" binding:"required"`
|
|
Title string `json:"title" binding:"required"`
|
|
Content string `json:"content" binding:"required"`
|
|
Summary *string `json:"summary"`
|
|
}
|
|
|
|
// UpdateVersionRequest is the request body for updating a version
|
|
type UpdateVersionRequest struct {
|
|
Title *string `json:"title"`
|
|
Content *string `json:"content"`
|
|
Summary *string `json:"summary"`
|
|
Status *string `json:"status"`
|
|
}
|
|
|
|
// SubmitForReviewRequest for submitting a version for review
|
|
type SubmitForReviewRequest struct {
|
|
Comment *string `json:"comment"`
|
|
}
|
|
|
|
// ApproveVersionRequest for approving a version (DSB)
|
|
type ApproveVersionRequest struct {
|
|
Comment *string `json:"comment"`
|
|
ScheduledPublishAt *string `json:"scheduled_publish_at"` // ISO 8601 datetime for scheduled publishing
|
|
}
|
|
|
|
// RejectVersionRequest for rejecting a version
|
|
type RejectVersionRequest struct {
|
|
Comment string `json:"comment" binding:"required"`
|
|
}
|
|
|
|
// VersionCompareResponse for comparing versions
|
|
type VersionCompareResponse struct {
|
|
Published *DocumentVersion `json:"published,omitempty"`
|
|
Draft *DocumentVersion `json:"draft"`
|
|
Diff *string `json:"diff,omitempty"`
|
|
Approvals []VersionApproval `json:"approvals"`
|
|
}
|
|
|
|
// PendingConsentResponse for pending consents with deadline info
|
|
type PendingConsentResponse struct {
|
|
Document LegalDocument `json:"document"`
|
|
Version DocumentVersion `json:"version"`
|
|
DeadlineAt time.Time `json:"deadline_at"`
|
|
DaysLeft int `json:"days_left"`
|
|
IsOverdue bool `json:"is_overdue"`
|
|
}
|
|
|
|
// AccountStatusResponse for account status check
|
|
type AccountStatusResponse struct {
|
|
Status string `json:"status"` // 'active', 'suspended'
|
|
PendingConsents []PendingConsentResponse `json:"pending_consents,omitempty"`
|
|
SuspensionReason *string `json:"suspension_reason,omitempty"`
|
|
CanAccess bool `json:"can_access"`
|
|
}
|