e34f7cb507
CI / detect-changes (push) Successful in 7s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 11s
CI / loc-budget (push) Failing after 14s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 30s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
Phase 1 of the workspace-cutover initiative: compliance becomes the
single source of truth for documents. Step one is making the existing
compliance_legal_documents workflow rich enough to express the DSB→
Mandant approval pattern that the workspace's 5-stage UI needed.
Migration 148:
- Adds CHECK constraint on status (was free-form VARCHAR20)
- Allows: draft, review, review_internal, review_client, approved,
published, archived, rejected (legacy "review" kept for backward
compat — 0 existing rows so no backfill needed)
- Adds CHECK on approvals.action with extended values:
submitted_internal, submitted_client, approved_internal,
approved_client, rejected_internal, rejected_client
- Adds 6 new columns for the richer audit trail: submitted_by/at,
approved_internal_by/at, approved_client_by/at
Service:
- New methods submit_internal_review, approve_internal, approve_client
- submit_review / approve kept as backwards-compat aliases that map to
the new methods
- reject() now reads current status to log specific rejected_internal
or rejected_client action
- _version_to_response includes all new audit fields
Routes:
- POST /versions/{id}/submit-internal-review
- POST /versions/{id}/approve-internal (DSB sagt OK → Mandant ist dran)
- POST /versions/{id}/approve-client (Mandant sagt OK → approved)
- Existing submit-review / approve endpoints stay but map through aliases
Schema:
- VersionResponse extended with optional submitted_by/at,
approved_internal_by/at, approved_client_by/at fields
This unlocks Phase 2 (Generate-All in compliance generator), Phase 3
(Document-Library tab in admin), Phase 4 (workspace cutover — drop its
own document storage and route everything through this lifecycle).
[migration-approved]
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
130 lines
3.0 KiB
Python
130 lines
3.0 KiB
Python
"""
|
|
Legal document schemas — Rechtliche Texte with versioning + approval.
|
|
|
|
Phase 1 Step 4: extracted from ``compliance.api.legal_document_routes``.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class DocumentCreate(BaseModel):
|
|
type: str
|
|
name: str
|
|
description: Optional[str] = None
|
|
mandatory: bool = False
|
|
tenant_id: Optional[str] = None
|
|
|
|
|
|
class DocumentResponse(BaseModel):
|
|
id: str
|
|
tenant_id: Optional[str]
|
|
type: str
|
|
name: str
|
|
description: Optional[str]
|
|
mandatory: bool
|
|
created_at: datetime
|
|
updated_at: Optional[datetime]
|
|
|
|
|
|
class VersionCreate(BaseModel):
|
|
document_id: str
|
|
version: str
|
|
language: str = "de"
|
|
title: str
|
|
content: str
|
|
summary: Optional[str] = None
|
|
created_by: Optional[str] = None
|
|
|
|
|
|
class VersionUpdate(BaseModel):
|
|
title: Optional[str] = None
|
|
content: Optional[str] = None
|
|
summary: Optional[str] = None
|
|
version: Optional[str] = None
|
|
language: Optional[str] = None
|
|
|
|
|
|
class VersionResponse(BaseModel):
|
|
id: str
|
|
document_id: str
|
|
version: str
|
|
language: str
|
|
title: str
|
|
content: str
|
|
summary: Optional[str]
|
|
status: str
|
|
created_by: Optional[str]
|
|
# Legacy single-approval (4-stage)
|
|
approved_by: Optional[str]
|
|
approved_at: Optional[datetime]
|
|
# 5-stage Trail
|
|
submitted_by: Optional[str] = None
|
|
submitted_at: Optional[datetime] = None
|
|
approved_internal_by: Optional[str] = None
|
|
approved_internal_at: Optional[datetime] = None
|
|
approved_client_by: Optional[str] = None
|
|
approved_client_at: Optional[datetime] = None
|
|
rejection_reason: Optional[str]
|
|
created_at: datetime
|
|
updated_at: Optional[datetime]
|
|
|
|
|
|
class ApprovalHistoryEntry(BaseModel):
|
|
id: str
|
|
version_id: str
|
|
action: str
|
|
approver: Optional[str]
|
|
comment: Optional[str]
|
|
created_at: datetime
|
|
|
|
|
|
class ActionRequest(BaseModel):
|
|
approver: Optional[str] = None
|
|
comment: Optional[str] = None
|
|
|
|
|
|
class UserConsentCreate(BaseModel):
|
|
user_id: str
|
|
document_id: str
|
|
document_version_id: Optional[str] = None
|
|
document_type: str
|
|
consented: bool = True
|
|
ip_address: Optional[str] = None
|
|
user_agent: Optional[str] = None
|
|
|
|
|
|
class CookieCategoryCreate(BaseModel):
|
|
name_de: str
|
|
name_en: Optional[str] = None
|
|
description_de: Optional[str] = None
|
|
description_en: Optional[str] = None
|
|
is_required: bool = False
|
|
sort_order: int = 0
|
|
|
|
|
|
class CookieCategoryUpdate(BaseModel):
|
|
name_de: Optional[str] = None
|
|
name_en: Optional[str] = None
|
|
description_de: Optional[str] = None
|
|
description_en: Optional[str] = None
|
|
is_required: Optional[bool] = None
|
|
sort_order: Optional[int] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
|
|
__all__ = [
|
|
"DocumentCreate",
|
|
"DocumentResponse",
|
|
"VersionCreate",
|
|
"VersionUpdate",
|
|
"VersionResponse",
|
|
"ApprovalHistoryEntry",
|
|
"ActionRequest",
|
|
"UserConsentCreate",
|
|
"CookieCategoryCreate",
|
|
"CookieCategoryUpdate",
|
|
]
|