refactor(go/ucca): split license_policy, models, pdf_export, escalation_store, obligations_registry

Split 5 oversized files (501-583 LOC each) into focused units all under 500 LOC:
- license_policy.go → +_types.go (engine logic / type definitions)
- models.go → +_intake.go, +_assessment.go (enums+domains / intake structs / output+DB types)
- pdf_export.go → +_markdown.go (PDF export / markdown export)
- escalation_store.go → +_dsb.go (main escalation ops / DSB pool ops)
- obligations_registry.go → +_grouping.go (registry core / grouping methods)

All files remain in package ucca. Zero behavior changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-19 10:03:51 +02:00
parent 3f1444541f
commit f7a5f9e1ed
11 changed files with 759 additions and 743 deletions

View File

@@ -11,66 +11,6 @@ import (
// Handles license/copyright compliance for standards and norms
// =============================================================================
// LicensedContentFacts represents the license-related facts from the wizard
type LicensedContentFacts struct {
Present bool `json:"present"`
Publisher string `json:"publisher"` // DIN_MEDIA, VDI, VDE, ISO, etc.
LicenseType string `json:"license_type"` // SINGLE_WORKSTATION, NETWORK_INTRANET, etc.
AIUsePermitted string `json:"ai_use_permitted"` // YES, NO, UNKNOWN
ProofUploaded bool `json:"proof_uploaded"`
OperationMode string `json:"operation_mode"` // LINK_ONLY, NOTES_ONLY, FULLTEXT_RAG, TRAINING
DistributionScope string `json:"distribution_scope"` // SINGLE_USER, COMPANY_INTERNAL, etc.
ContentType string `json:"content_type"` // NORM_FULLTEXT, CUSTOMER_NOTES, etc.
}
// LicensePolicyResult represents the evaluation result
type LicensePolicyResult struct {
Allowed bool `json:"allowed"`
EffectiveMode string `json:"effective_mode"` // The mode that will actually be used
Reason string `json:"reason"`
Gaps []LicenseGap `json:"gaps"`
RequiredControls []LicenseControl `json:"required_controls"`
StopLine *LicenseStopLine `json:"stop_line,omitempty"` // If hard blocked
OutputRestrictions *OutputRestrictions `json:"output_restrictions"`
EscalationLevel string `json:"escalation_level"`
RiskScore int `json:"risk_score"`
}
// LicenseGap represents a license-related gap
type LicenseGap struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Controls []string `json:"controls"`
Severity string `json:"severity"`
}
// LicenseControl represents a required control for license compliance
type LicenseControl struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
WhatToDo string `json:"what_to_do"`
Evidence []string `json:"evidence_needed"`
}
// LicenseStopLine represents a hard block
type LicenseStopLine struct {
ID string `json:"id"`
Title string `json:"title"`
Message string `json:"message"`
Outcome string `json:"outcome"` // NOT_ALLOWED, NOT_ALLOWED_UNTIL_LICENSE_CLEARED
}
// OutputRestrictions defines how outputs should be filtered
type OutputRestrictions struct {
AllowQuotes bool `json:"allow_quotes"`
MaxQuoteLength int `json:"max_quote_length"` // in characters
RequireCitation bool `json:"require_citation"`
AllowCopy bool `json:"allow_copy"`
AllowExport bool `json:"allow_export"`
}
// LicensePolicyEngine evaluates license compliance
type LicensePolicyEngine struct {
// Configuration can be added here
@@ -144,7 +84,6 @@ func (e *LicensePolicyEngine) evaluateLinkOnlyMode(facts *LicensedContentFacts,
result.Reason = "Link-only Modus ist ohne spezielle Lizenz erlaubt"
result.RiskScore = 0
// Very restrictive output
result.OutputRestrictions = &OutputRestrictions{
AllowQuotes: false,
MaxQuoteLength: 0,
@@ -153,7 +92,6 @@ func (e *LicensePolicyEngine) evaluateLinkOnlyMode(facts *LicensedContentFacts,
AllowExport: false,
}
// Recommend control for proper setup
result.RequiredControls = append(result.RequiredControls, LicenseControl{
ID: "CTRL-LINK-ONLY-MODE",
Title: "Link-only / Evidence Navigator aktivieren",
@@ -170,7 +108,6 @@ func (e *LicensePolicyEngine) evaluateNotesOnlyMode(facts *LicensedContentFacts,
result.Reason = "Notes-only Modus mit kundeneigenen Zusammenfassungen"
result.RiskScore = 10
// Allow paraphrased content
result.OutputRestrictions = &OutputRestrictions{
AllowQuotes: false, // No direct quotes from norms
MaxQuoteLength: 0,
@@ -244,7 +181,6 @@ func (e *LicensePolicyEngine) evaluateExcerptOnlyMode(facts *LicensedContentFact
func (e *LicensePolicyEngine) evaluateFulltextRAGMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
result.RiskScore = 60
// Check if AI use is explicitly permitted AND proof is uploaded
if facts.AIUsePermitted == "YES" && facts.ProofUploaded {
result.EffectiveMode = "FULLTEXT_RAG"
result.Allowed = true
@@ -290,7 +226,6 @@ func (e *LicensePolicyEngine) evaluateFulltextRAGMode(facts *LicensedContentFact
result.EscalationLevel = "E3"
// Set stop line
result.StopLine = &LicenseStopLine{
ID: "STOP_FULLTEXT_WITHOUT_PROOF",
Title: "Volltext-RAG blockiert",
@@ -312,7 +247,6 @@ func (e *LicensePolicyEngine) evaluateFulltextRAGMode(facts *LicensedContentFact
func (e *LicensePolicyEngine) evaluateTrainingMode(facts *LicensedContentFacts, result *LicensePolicyResult) {
result.RiskScore = 80
// Training is almost always blocked for standards
if facts.AIUsePermitted == "YES" && facts.ProofUploaded && facts.LicenseType == "AI_LICENSE" {
result.EffectiveMode = "TRAINING"
result.Allowed = true
@@ -353,10 +287,8 @@ func (e *LicensePolicyEngine) evaluateTrainingMode(facts *LicensedContentFacts,
// applyPublisherRestrictions applies publisher-specific rules
func (e *LicensePolicyEngine) applyPublisherRestrictions(facts *LicensedContentFacts, result *LicensePolicyResult) {
// DIN Media specific restrictions
if facts.Publisher == "DIN_MEDIA" {
if facts.AIUsePermitted != "YES" {
// DIN Media explicitly prohibits AI use without license
if facts.OperationMode == "FULLTEXT_RAG" || facts.OperationMode == "TRAINING" {
result.Allowed = false
result.EffectiveMode = "LINK_ONLY"
@@ -394,7 +326,6 @@ func (e *LicensePolicyEngine) applyPublisherRestrictions(facts *LicensedContentF
// checkDistributionScope checks if distribution scope matches license type
func (e *LicensePolicyEngine) checkDistributionScope(facts *LicensedContentFacts, result *LicensePolicyResult) {
// Single workstation license with broad distribution
if facts.LicenseType == "SINGLE_WORKSTATION" {
if facts.DistributionScope == "COMPANY_INTERNAL" ||
facts.DistributionScope == "SUBSIDIARIES" ||
@@ -413,7 +344,6 @@ func (e *LicensePolicyEngine) checkDistributionScope(facts *LicensedContentFacts
}
}
// Network license with external distribution
if facts.LicenseType == "NETWORK_INTRANET" {
if facts.DistributionScope == "EXTERNAL_CUSTOMERS" {
result.Gaps = append(result.Gaps, LicenseGap{
@@ -433,16 +363,16 @@ func (e *LicensePolicyEngine) checkDistributionScope(facts *LicensedContentFacts
// CanIngestFulltext checks if fulltext ingestion is allowed
func (e *LicensePolicyEngine) CanIngestFulltext(facts *LicensedContentFacts) bool {
if !facts.Present {
return true // No licensed content, no restrictions
return true
}
switch facts.OperationMode {
case "LINK_ONLY":
return false // Only metadata/references
return false
case "NOTES_ONLY":
return false // Only customer notes, not fulltext
return false
case "EXCERPT_ONLY":
return false // Only short excerpts
return false
case "FULLTEXT_RAG":
return facts.AIUsePermitted == "YES" && facts.ProofUploaded
case "TRAINING":
@@ -457,8 +387,6 @@ func (e *LicensePolicyEngine) CanIngestNotes(facts *LicensedContentFacts) bool {
if !facts.Present {
return true
}
// Notes are allowed in most modes
return facts.OperationMode == "NOTES_ONLY" ||
facts.OperationMode == "EXCERPT_ONLY" ||
facts.OperationMode == "FULLTEXT_RAG" ||
@@ -471,40 +399,17 @@ func (e *LicensePolicyEngine) GetEffectiveMode(facts *LicensedContentFacts) stri
return result.EffectiveMode
}
// LicenseIngestDecision represents the decision for ingesting a document
type LicenseIngestDecision struct {
AllowFulltext bool `json:"allow_fulltext"`
AllowNotes bool `json:"allow_notes"`
AllowMetadata bool `json:"allow_metadata"`
Reason string `json:"reason"`
EffectiveMode string `json:"effective_mode"`
}
// DecideIngest returns the ingest decision for a document
func (e *LicensePolicyEngine) DecideIngest(facts *LicensedContentFacts) *LicenseIngestDecision {
result := e.Evaluate(facts)
decision := &LicenseIngestDecision{
return &LicenseIngestDecision{
AllowMetadata: true, // Metadata is always allowed
AllowNotes: e.CanIngestNotes(facts),
AllowFulltext: e.CanIngestFulltext(facts),
Reason: result.Reason,
EffectiveMode: result.EffectiveMode,
}
return decision
}
// LicenseAuditEntry represents an audit log entry for license decisions
type LicenseAuditEntry struct {
Timestamp time.Time `json:"timestamp"`
TenantID string `json:"tenant_id"`
DocumentID string `json:"document_id,omitempty"`
Facts *LicensedContentFacts `json:"facts"`
Decision string `json:"decision"` // ALLOW, DENY, DOWNGRADE
EffectiveMode string `json:"effective_mode"`
Reason string `json:"reason"`
StopLineID string `json:"stop_line_id,omitempty"`
}
// FormatAuditEntry creates an audit entry for logging