Files
nexarch/internal/migrationrole/mapping.go
patrickandClaude Sonnet 5 25812b47b8 CUT-01: trockenlauf-1-entwicklung - korrekturen aus iteration 1
Iteration 1 (Laeufe 1.1-1.5 gegen den Wegwerf-Cluster auf Host 204):

- I-1 (Lauf 1.1, MAP-01/MAP-03): Export erwartete tenants.domain und
  users.name, die Altsysteme fuehren tenant_domains bzw. users.username.
  Behoben ueber Export-Sichten (Schritt EXP-01) statt Aenderung der
  MAP-Pakete.
- I-2 (Lauf 1.2, MAP-02/MAP-03): einseitige Mandanten (nur in einem
  Altsystem) wurden von InsertCandidates verworfen und von usermatch
  uebersprungen und waeren nie migriert worden. Jetzt pending in der Map
  (Freigabe bleibt Pflicht), Benutzer als einseitige Kandidaten.
- I-3 (Lauf 1.3, COR-03): dokumentierte archivmail-Rollen domain_admin,
  auditor, domain_auditor ohne Core-Rolle. Ergaenzt (Pruefer -> user),
  superadmin bleibt fail-closed.
- I-4 (Lauf 1.4, TAR-01 -> MAI-03): retention_objects ohne
  data_subject_ref, offene DSGVO-Anfragen liefen ins Leere. TAR-01
  uebernimmt die betroffene Person aus der Quelle.

Lauf 1.5 lief vollstaendig durch. Protokolle unter docs/cut-01/iteration-1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-14 20:53:52 +00:00

78 lines
2.9 KiB
Go

// Package migrationrole implementiert COR-03: die Uebernahme der
// Rollen-/Rechtezuordnung aus archivmail (Freitext-Rolle) und archivdms
// (Berechtigungsgruppe) in Core RBAC-01, ueber eine feste, dokumentierte
// Mapping-Tabelle statt einer 1:1-Freitext-Uebernahme.
package migrationrole
import (
"fmt"
"gitea.perlbach24.de/scripte/nexarch/internal/rbac"
)
// ErrUnmappedRole wird geliefert, wenn fuer eine source_role/source_system-
// Kombination keine Core-Rolle hinterlegt ist. Ein solcher Eintrag darf nie
// stillschweigend eine Rolle erhalten (Akzeptanzkriterium 3).
type ErrUnmappedRole struct {
SourceSystem string
SourceRole string
}
func (e *ErrUnmappedRole) Error() string {
return fmt.Sprintf("migrationrole: keine core-rolle fuer %s-rolle %q hinterlegt", e.SourceSystem, e.SourceRole)
}
// archivmailRoleMap bildet jede bekannte archivmail-Textrolle auf genau eine
// Core-Rolle ab (Akzeptanzkriterium 2). archivmail kennt kein eigenes
// Rechtemodell (nur Freitext), daher die grobere Abbildung auf die drei
// Core-Grundrollen aus internal/rbac.
//
// domain_admin/auditor/domain_auditor sind die in datenmodell-altsysteme.md
// dokumentierten archivmail-Rollen, die im CUT-01-Trockenlauf (Befund I-3)
// fehlten. Core kennt keine Pruefer-Rolle, daher landen beide Auditor-
// Varianten bei der geringsten Rolle statt bei tenant_admin. superadmin
// bleibt bewusst ungemappt: Plattformkonten sind keine Mandantenrolle.
var archivmailRoleMap = map[string]rbac.Role{
"admin": rbac.RoleTenantAdmin,
"administrator": rbac.RoleTenantAdmin,
"domain_admin": rbac.RoleTenantAdmin,
"user": rbac.RoleUser,
"readonly": rbac.RoleUser,
"viewer": rbac.RoleUser,
"auditor": rbac.RoleUser,
"domain_auditor": rbac.RoleUser,
}
// archivdmsGroupMap bildet jede bekannte archivdms-Berechtigungsgruppe
// (permission_groups.name) auf genau eine Core-Rolle ab (Akzeptanzkriterium
// 1). archivdms hat das reifere Rechtemodell und dient laut Auftrag als
// Zielvorlage -- die hier verwendeten Gruppennamen sind die in diesem
// Projekt bislang beobachteten dms-Standardgruppen.
var archivdmsGroupMap = map[string]rbac.Role{
"vollzugriff": rbac.RoleTenantAdmin,
"administrator": rbac.RoleTenantAdmin,
"bearbeiter": rbac.RoleUser,
"leser": rbac.RoleUser,
"standard": rbac.RoleUser,
}
// CoreRole loest source_role (bereits auf Kleinschreibung normalisiert von
// Migrate) fuer das gegebene source_system zur Core-Rolle auf.
func CoreRole(sourceSystem, sourceRole string) (rbac.Role, error) {
var table map[string]rbac.Role
switch sourceSystem {
case "archivmail":
table = archivmailRoleMap
case "archivdms":
table = archivdmsGroupMap
default:
return "", fmt.Errorf("migrationrole: unbekanntes source_system %q", sourceSystem)
}
role, ok := table[sourceRole]
if !ok {
return "", &ErrUnmappedRole{SourceSystem: sourceSystem, SourceRole: sourceRole}
}
return role, nil
}