V01 Erste Runs

This commit is contained in:
Christoph Schwörer
2026-08-26 07:34:29 +02:00
parent 0ec86aed8c
commit 18edae75b6
493 changed files with 170180 additions and 14 deletions
+683
View File
@@ -0,0 +1,683 @@
---
name: run-experiment
description: Führt einen Versuchs-Prompt aus einer Prompt-Datei als messbaren Headless-Lauf aus (claude -p) und schreibt ein Messprotokoll mit Start-/Endzeit, Modell, Tokenverbrauch und weiteren Metriken. Verwenden bei "/run-experiment <Pfad-zur-Prompt-Datei>" oder wenn der User einen Versuch/ein Experiment ausführen und tracken will.
argument-hint: <Pfad zur Prompt-Datei> <Root-Verzeichnis>
version: 3.10.0
---
# RunExperiment – Versuchslauf mit Messprotokoll
Du führst einen wissenschaftlichen Versuchslauf für die Masterarbeit aus. Der Prompt aus der
übergebenen Datei wird als **separater Headless-Lauf** von Claude Code ausgeführt, damit
Tokenverbrauch und Modell exakt und maschinenlesbar erfasst werden. Anschließend
schreibst du ein Messprotokoll neben die Prompt-Datei.
## Parameter
- **Prompt** (Pflicht): Pfad zur Prompt-Datei (Markdown). Erstes Argument in `$ARGUMENTS`.
- **Root** (Pflicht): Verzeichnis, das als Root des Versuchslaufs dient. Zweites Argument.
Der Headless-Lauf wird mit diesem Verzeichnis als Arbeitsverzeichnis gestartet – es ist
die Wurzel der zu analysierenden Codebasis und wird nur GELESEN. Fehlt das Argument: den
User danach fragen und NICHT stillschweigend das aktuelle Verzeichnis verwenden. Vor dem
Lauf prüfen, dass das Verzeichnis existiert; sonst abbrechen und den User informieren.
- **Modell** (Pflicht, **kein Default**): Wird **vor jedem Lauf beim User erfragt** – siehe
Schritt 4 im Ablauf. Nennt der User das Modell bereits im Aufruf („… mit Opus 5"), diese
Angabe übernehmen und **nicht** erneut fragen. Ohne Angabe niemals stillschweigend ein
Modell wählen: Das Modell ist eine unabhängige Variable der Versuchsreihe.
- **Agentenmodus** (Pflicht, **kein Default**): Wird wie das Modell **vor jedem Lauf beim User
erfragt** – siehe Schritt 5 im Ablauf. Bestimmt, ob und welche Subagenten der Lauf einsetzen
darf. Drei Modi: `solo`, `builtin`, `custom` (Details in Schritt 5).
- **Effort** (Pflicht, **kein Default**): Denkaufwand des Modells. Wird wie Modell und
Agentenmodus **vor jedem Lauf beim User erfragt** – siehe Schritt 6.
Alle Ausgaben des Laufs (Ergebnisdateien, Messprotokoll, Rohdaten) landen in einem **neuen
Laufverzeichnis neben der Prompt-Datei**, niemals im Root-Verzeichnis:
```
<Verzeichnis der Prompt-Datei>\
<NN>_Prompt.md
<ModellID>\<Agentenmodus>\<Effort>\
<NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>\
Protokoll.md
RawResult.json
Stderr.log
_meta\ (Laufsteuerung: combined_prompt.md, before.txt, after.txt, Zeitstempel,
subagenten.md/.json, anforderungen.md/.json)
Ergebnisse\ (NUR vom Prompt erzeugte Artefakte, z. B. StRS.md, SyRS.md, ...)
```
**Die unabhängigen Variablen bilden die Ordnerebenen, nicht den Dateinamen:**
- `<ModellID>` – die an `--model` übergebene ID, z. B. `claude-sonnet-5`, `claude-opus-5`,
`claude-fable-5`
- `<Agentenmodus>` – `solo`, `builtin` oder `custom`
- `<Effort>` – `low`, `medium`, `high`, `xhigh` oder `max`
Der Verzeichnisname trägt nur noch, was den einzelnen Lauf identifiziert:
- `<NN>` – Nummernpräfix der Prompt-Datei (z. B. `01` bei `01_Prompt.md`)
- `<yyyy-MM-dd_HHmmss>` – Startzeit **sekundengenau**
- `<skillversion>` – Version dieses Skills zum Startzeitpunkt, z. B. `v3.10.0`
- `<id4>` – 4 Hexstellen Zufall; garantiert Eindeutigkeit auch bei gleichzeitigem Start
**Warum Ordnerebenen statt Namensbestandteile:** Der Name wuchs mit jeder neuen unabhängigen
Variable weiter und war mit fünf Bestandteilen kaum noch lesbar. Als Ordnerebenen sind die
Bedingungen navigierbar, je Zelle abzählbar (`ls <modell>/<modus>/<effort> | wc -l` ergibt
unmittelbar die Anzahl der Messpunkte) und beim Hinzufügen einer weiteren Variable erweiterbar,
ohne bestehende Namen zu brechen. Die Angaben sind **redundant zum Protokoll** – bei Widerspruch
gilt das Protokoll.
**Jeder Lauf ist vollständig selbstenthalten.** Sämtliche Steuerdateien liegen in `_meta\`
**innerhalb** des Laufverzeichnisses – nicht im gemeinsamen Scratchpad. Das ist Voraussetzung
für parallele Läufe (siehe „Parallele Läufe") und archiviert nebenbei den exakt gesendeten
Prompt je Lauf. `Ergebnisse\` enthält ausschließlich die vom Prompt geforderten Artefakte.
## Ablauf
### 1. Vorbereitung
1. Prompt-Datei lesen. Existiert sie nicht: abbrechen und den User informieren.
2. Aus dem Metadaten-Block der Prompt-Datei (falls vorhanden) Versuch/Iteration übernehmen.
3. **CLI-Pfad auflösen.** Unter Windows liegt `claude` in der Regel **nicht im PATH**. Erst
`Get-Command claude -ErrorAction SilentlyContinue` versuchen; schlägt das fehl, auf die
VSCode-Extension zurückfallen und die höchste Versionsnummer wählen:
```powershell
$claude = (Get-Command claude -ErrorAction SilentlyContinue).Source
if (-not $claude) {
$claude = Get-ChildItem "$env:USERPROFILE\.vscode\extensions\anthropic.claude-code-*-win32-x64\resources\native-binary\claude.exe" |
Sort-Object FullName | Select-Object -Last 1 -ExpandProperty FullName
}
```
Findet sich keine ausführbare Datei: abbrechen und den User informieren. Den aufgelösten
Pfad fürs Protokoll festhalten.
4. **Modell beim User erfragen.** Hat der User das Modell nicht bereits im Aufruf genannt,
**immer** per `AskUserQuestion` nachfragen – auch dann, wenn frühere Läufe derselben
Versuchsreihe ein bestimmtes Modell verwendet haben. Es gibt bewusst keinen Default.
Als Optionen die vollen Modell-IDs anbieten, nicht die Kurzformen:
| Modell-ID | Einordnung |
|---|---|
| `claude-opus-5` | stärkstes Modell, teuerster Lauf |
| `claude-sonnet-5` | 1-Mio.-Kontextfenster, für große Codebasen meist ausreichend |
| `claude-fable-5` | schnell und günstig |
| `claude-haiku-4-5-20251001` | günstigstes Modell |
In der Frage den letzten verwendeten Stand nennen, damit der User bewusst wechseln oder
bewusst wiederholen kann (z. B. „Lauf 3 lief mit `claude-sonnet-5`, 11.516.200 Tokens, 23:40").
**Niemals die Kurzformen `opus`, `sonnet`, `fable` an `--model` übergeben.** Sie lösen auf
das jeweils neueste Modell auf und verschieben sich über die Zeit – damit wäre die
Versuchsbedingung nicht reproduzierbar. Für ein 1-Mio.-Token-Fenster die Variante mit
`[1m]`-Suffix wählen (z. B. `claude-opus-5[1m]`).
Weicht das gewählte Modell vom letzten Lauf ab, im Protokoll unter „Anmerkungen" als
geänderte Versuchsbedingung vermerken und in der Änderungshistorie des Skills ergänzen.
5. **Agentenmodus beim User erfragen.** Wie beim Modell: kein Default, immer nachfragen, wenn
der User den Modus nicht bereits im Aufruf genannt hat. Der Modus ist die zentrale
Unterscheidung zwischen den Versuchen der Arbeit.
| Modus | Versuch | Bedeutung |
|---|---|---|
| `solo` | **V1** | Ein Thread, ein Kontext. Der Lauf darf **keine** Subagenten starten. |
| `builtin` | **V1b** | Eingebaute Subagenten erlaubt (`Explore`, `general-purpose`). |
| `custom` | **V2** | Nur **vordefinierte, geprompte Agenten** aus `--agents`. |
Flags je Modus – zusätzlich zur Standardkonfiguration aus Abschnitt 2:
```powershell
switch ($modus) {
'solo' { $agentFlags = @('--disallowedTools','Task','Agent','Workflow') }
'builtin' { $agentFlags = @() }
'custom' { $agentFlags = @('--agents', (Get-Content $agentDatei -Raw)) }
}
```
**Warum `Task`, `Agent` *und* `Workflow`:** Welchen Namen das Subagenten-Werkzeug in der
jeweiligen CLI-Version trägt, ist nicht dokumentiert – im Binary von 2.1.245 kommen `Task`
und `Agent` vor; beide zu sperren ist unschädlich, ein nicht existierender Name läuft ins
Leere. `Workflow` orchestriert ebenfalls Subagenten und muss mitgesperrt werden: Im
Verifikationstest (2026-08-25, CLI 2.1.245) wich der Agent nach der Sperre von `Task`/`Agent`
**genau darauf** aus. Verifiziert wurden `spawned: 0`, die Antwort „KEINE SUBAGENTEN
MOEGLICH" und ein Denial auf `Workflow`. Kontrolle nach dem Lauf: `subagent_stats.spawned` **muss** im
Modus `solo` genau `0` sein – andernfalls hat die Sperre nicht gegriffen und der Lauf ist
als Fehlmessung zu kennzeichnen.
Im Modus `solo` sind **Permission-Denials auf `Task`/`Agent` erwartbar**, wenn der Agent zu
delegieren versucht. Sie sind im Protokoll getrennt von sonstigen Denials auszuweisen und
**nicht** als Einschränkung der Werkzeugkonfiguration zu werten – sie sind die Bedingung selbst.
Für `custom` (V2): Die Agentendefinitionen liegen als JSON-Datei **neben der Prompt-Datei**
(z. B. `Versuche/Versuch_02/02_Agents.json`), **nicht** im Codebasis-Snapshot. Sie werden wie
der Prompt per SHA-256 gehasht und im Protokoll geführt. So bleibt der eingefrorene Snapshot
unangetastet und die Agentenkonfiguration ist eine dokumentierte, versionierte
Versuchsbedingung. Format siehe `claude --help` zu `--agents`.
6. **Effort beim User erfragen.** Kein Default, immer nachfragen, wenn der User die Stufe nicht
bereits im Aufruf genannt hat. Stufen: `low`, `medium`, `high`, `xhigh`, `max`.
Übergabe per `--effort <stufe>`.
In der Frage den bisherigen Stand nennen. **Alle Läufe bis einschließlich Lauf B liefen auf
`high`** – geerbt aus der Sitzungseinstellung, nicht bewusst gesetzt; der Wert wurde
nachträglich aus den Transkripten belegt. Wer die Stufe wechselt, ändert die
Versuchsbedingung und macht den Lauf mit den bisherigen unvergleichbar.
**Wichtig – der Effort ist aus `RawResult.json` nicht rekonstruierbar.** Das Ergebnisobjekt
enthält kein `effort`-Feld. Nur das Session-Transkript hält ihn je Nachricht fest
(`"effort": "high"`). Fehlt er im Protokoll, ist die Bedingung nachträglich allein über das
Transkript belegbar – und das nur, solange die Session persistiert ist.
7. Messgrößen VOR dem Lauf erfassen (PowerShell):
- Startzeit: `Get-Date -Format o`
- SHA-256 der Prompt-Datei: `(Get-FileHash <datei> -Algorithm SHA256).Hash`
- Claude-Code-Version: `& $claude --version`
- Git-Zustand des Root-Verzeichnisses: `git -C <root> rev-parse HEAD` und
`git -C <root> status --porcelain` (dirty ja/nein)
- Git-Commit dieses Repos (Stand der Prompt-Datei): `git rev-parse HEAD`
8. **Kollisionsfreies Laufverzeichnis anlegen.** Sekundengenau, mit Agentenmodus und
Zufalls-ID; bei Namenskollision neu würfeln:
```powershell
# Bedingungen werden Ordnerebenen, nicht Namensbestandteile
$zelle = Join-Path (Join-Path $modell $modus) $effort
$skillVer = 'v3.10.0' # entspricht version: im Frontmatter dieses Skills
do {
$id4 = '{0:x4}' -f (Get-Random -Maximum 65536)
$lauf = Join-Path "<promptverzeichnis>\$zelle" "<NN>_Lauf_$(Get-Date -Format 'yyyy-MM-dd_HHmmss')_${skillVer}-$id4"
} while (Test-Path $lauf)
New-Item -ItemType Directory -Force "$lauf\Ergebnisse" | Out-Null
New-Item -ItemType Directory -Force "$lauf\_meta" | Out-Null
```
9. Dateibestand des Roots vor dem Lauf sichern – das Root soll unverändert bleiben, jede
Änderung dort ist eine Auffälligkeit fürs Protokoll. Ziel ist `_meta\` **im Laufverzeichnis**,
nicht der gemeinsame Scratchpad:
```powershell
# Leerwertsicher: -Value erzwingt das Schreiben auch bei sauberem Root.
Set-Content -Path "$lauf\_meta\before.txt" -Value (git -C <root> status --porcelain | Out-String)
```
**Nicht** `git ... | Set-Content <datei>` verwenden: Ist die Pipeline leer (sauberes Root),
schreibt `Set-Content` die Datei nicht und lässt einen alten Inhalt stehen. Der
Vorher/Nachher-Vergleich meldet dann eine Abweichung, die es nicht gibt.
(Kein Git-Repo? Dann rekursive Dateiliste mit LastWriteTime nach `_meta\` schreiben.)
**Isolation: Die Codebasis ist ein eingefrorener Snapshot ohne KI-Konfigurationen.**
Der Untersuchungsgegenstand wurde einmalig um alle KI-Assistenz-Konfigurationen bereinigt
(`.claude/`, `.agents/`, `.codex/`, `.cursor/`, `.serena/`, `.opencode/`, `.memory-mcp/`,
`CLAUDE.md`, `AGENTS.md`, `.mcp.json`, `opencode.json`, `skills-lock.json`, `.coderabbit.yaml`,
`.aiignore`, `.claudeignore`, `.cursorignore`), und das GitHub-Remote ist entkoppelt. Die
Bedingung „keine Agentendateien, keine MCP-Server" ist damit eine **Eigenschaft des Snapshots**
und muss nicht pro Lauf hergestellt werden. Damit entfällt jeder destruktive Vorbereitungsschritt.
Vor jedem Lauf den Snapshot **prüfen** – nicht bereinigen:
```powershell
$muster = 'CLAUDE\.md|AGENTS\.md|GEMINI\.md|\.mcp\.json|opencode\.json|skills-lock\.json|' +
'\.coderabbit\.yaml|\.aiignore|\.claudeignore|\.cursorignore|copilot-instructions|' +
'^\.(claude|agents|codex|cursor|serena|opencode|memory-mcp|continue|gemini|windsurf)/'
$fund = git -C <root> ls-files | Select-String -Pattern $muster
if ($fund) { "WARNUNG: KI-Konfigurationen im Snapshot:"; $fund }
```
**Den Regex nicht „vereinfachen".** Die Anker (`(^|/)`, `$`, führender Punkt) sind notwendig.
`Select-String` arbeitet in PowerShell standardmäßig **case-insensitiv**; ein gelockertes Muster
schlägt deshalb auf echte Produktdateien an. In dieser Codebasis etwa:
`src/backend/Centron.BL/ArtificialIntelligence/Chat/ClaudeCodeChatModelClient.cs` und
`GoogleGeminiChatModelClient.cs` – Bestandteile des KI-Assistenz-Features der ERP-Suite und
damit legitimer Untersuchungsgegenstand, keine Werkzeugkonfiguration. Bei einem Treffer immer
erst die konkreten Pfade ansehen, bevor Alarm ausgelöst wird.
Findet die Prüfung echte Treffer: **abbrechen und den User informieren – nicht eigenmächtig löschen.**
Der Codebasis-Snapshot ist ein Messinstrument. Eine Änderung daran ist eine Änderung der
Versuchsbedingung und macht Läufe untereinander unvergleichbar; sie gehört abgestimmt,
committet und im Protokoll dokumentiert.
**Das Remote ist entkoppelt.** Im Codebasis-Repo wird niemals gepusht, gefetcht oder ein Remote
hinzugefügt. Der Snapshot bleibt eingefroren.
### 2. Ausführung (Headless-Lauf)
Dem Prompt eine Ausgabe-Anweisung anhängen, damit die Ergebnisse im Laufverzeichnis landen
und nicht im Root. Dazu den Prompttext um einen Abschnitt ergänzen (Prompt-Datei selbst
NICHT verändern – nur den per stdin übergebenen Text):
```
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`<absoluter Pfad zum Laufverzeichnis>\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
```
Dann den kombinierten Prompt per stdin an `claude -p` übergeben. `--add-dir` gibt dem
Headless-Lauf Schreibrecht auf das Laufverzeichnis außerhalb seines Arbeitsverzeichnisses.
Versuchsläufe können lange dauern – **immer als Background-Task starten** (`run_in_background`),
nicht mit Foreground-Timeout arbeiten:
```powershell
$lauf = "<absoluter Pfad zum Laufverzeichnis>"
$prompt = (Get-Content "<prompt-datei>" -Raw) + "`n`n<Ausgabe-Anweisung>"
# Steuerdateien IMMER ins Laufverzeichnis - nie in den gemeinsamen Scratchpad (parallelfaehig)
Set-Content -Path "$lauf\_meta\combined_prompt.md" -Value $prompt -Encoding utf8
Set-Content -Path "$lauf\_meta\startzeit.txt" -Value (Get-Date -Format o)
# Schreibende und bauende Shell-Kommandos sperren – die Codebasis wird nur gelesen.
$denyBash = @(
'Bash(rm:*)','Bash(rmdir:*)','Bash(mv:*)','Bash(cp:*)','Bash(dd:*)',
'Bash(truncate:*)','Bash(chmod:*)','Bash(chown:*)','Bash(ln:*)','Bash(tee:*)',
'Bash(sed -i:*)','Bash(git checkout:*)','Bash(git restore:*)','Bash(git clean:*)',
'Bash(git reset:*)','Bash(git add:*)','Bash(git commit:*)','Bash(git push:*)',
'Bash(dotnet:*)','Bash(msbuild:*)','Bash(npm install:*)','Bash(nuget:*)'
)
$denyPs = @(
'PowerShell(Remove-Item:*)','PowerShell(Move-Item:*)','PowerShell(Copy-Item:*)',
'PowerShell(New-Item:*)','PowerShell(Set-Content:*)','PowerShell(Add-Content:*)',
'PowerShell(Clear-Content:*)','PowerShell(Out-File:*)','PowerShell(Set-ItemProperty:*)',
'PowerShell(dotnet:*)','PowerShell(msbuild:*)'
)
Set-Location "<root>"
Get-Content "$lauf\_meta\combined_prompt.md" -Raw |
& $claude -p `
--output-format json `
--safe-mode `
--strict-mcp-config `
--permission-mode acceptEdits `
--allowedTools "Bash" "PowerShell" `
--disallowedTools @($denyBash + $denyPs) `
--model <vom User gewaehlte Modell-ID aus Schritt 4> `
--effort <vom User gewaehlte Stufe aus Schritt 6> `
@agentFlags `
--add-dir "$lauf" `
2> "$lauf\Stderr.log" | Set-Content "$lauf\RawResult.json"
Set-Content -Path "$lauf\_meta\endzeit.txt" -Value (Get-Date -Format o)
```
Bedeutung der Flags:
| Flag | Zweck |
|---|---|
| `--safe-mode` | Isolation: CLAUDE.md, Skills, Plugins, Hooks, MCP-Server, Custom-Agenten, Commands und Output-Styles aus – ohne Dateieingriff. Auth, Modellwahl, eingebaute Tools und Permissions bleiben normal aktiv. |
| `--strict-mcp-config` | zweite Absicherung gegen MCP-Server aus Projekt- oder User-Konfiguration |
| `--permission-mode acceptEdits` | Schreibrechte für die Ergebnisdateien im Laufverzeichnis |
| `--allowedTools "Bash" "PowerShell"` | **Shell-Zugriff ohne Rückfrage** – Standard seit Iteration 02 |
| `--disallowedTools <Denylist>` | schreibende und bauende Kommandos gesperrt; Deny hat Vorrang vor Allow |
| `--add-dir "$lauf"` | Schreibziel außerhalb des Arbeitsverzeichnisses |
| `@agentFlags` | Agentenmodus aus Schritt 5: `solo` sperrt `Task`/`Agent`, `builtin` fügt nichts hinzu, `custom` übergibt `--agents` |
| `--effort <stufe>` | Denkaufwand aus Schritt 6; nicht aus `RawResult.json` rekonstruierbar, daher zwingend ins Protokoll |
| `--model <id>` | exakte Modellbindung aus Schritt 4; überschreibt die Modellpräferenz der User-Settings. Volle ID, keine Kurzform. |
Build-Kommandos (`dotnet`, `msbuild`, `nuget`, `npm install`) stehen bewusst auf der Denylist:
Sie würden `bin/`- und `obj/`-Artefakte im Root erzeugen und widersprechen der Methodenvorgabe
„statische Analyse, keine Ausführung".
**Grenzen der Denylist – ehrlich einordnen.** Pattern-Matching auf Shell-Kommandos ist nicht
lückenlos; Umleitungen, Pipes und verschachtelte Aufrufe lassen sich nicht vollständig abfangen.
Die belastbare Read-only-Garantie bleibt der Vorher/Nachher-Vergleich per
`git status --porcelain` aus Abschnitt 1 bzw. 3. Die Denylist senkt das Risiko, sie ersetzt die
Verifikation nicht.
**`--safe-mode` bleibt als zweite Sicherung aktiv.** Die primäre Isolation leistet der
bereinigte Snapshot (Abschnitt 1); `--safe-mode` fängt zusätzlich alles ab, was von außerhalb
des Roots wirken könnte – User-Level-Settings, global installierte Skills, Plugins, Hooks.
Verifiziert am 2026-08-25 gegen Version 2.1.245, dokumentiert als Begründung für den
Snapshot-Ansatz:
- `--safe-mode` verhindert zuverlässig das **Vorladen** von `CLAUDE.md`/`AGENTS.md` als
Systemanweisung. Kontrolltest ohne Werkzeuge: mit `--safe-mode` antwortet der Agent
„NICHTS VORGELADEN", ohne das Flag zitiert er den Inhalt der `CLAUDE.md`.
- `--safe-mode` verhindert **nicht**, dass der Agent solche Dateien als gewöhnliche Dateien
**findet und liest**. Im Smoke-Test mit Shell-Zugriff hat er genau das getan und den Inhalt
von `AGENTS.md` und `CLAUDE.md` wiedergegeben.
Genau deshalb reicht `--safe-mode` allein bei gewährtem Shell-Zugriff nicht aus, und die
KI-Konfigurationen wurden aus dem Snapshot entfernt statt nur deaktiviert.
**Trust-Hinweis auf stderr.** Liegt im Root eine `.claude/settings.json` mit
`permissions.allow`-Einträgen, meldet die CLI auf stderr sinngemäß „Ignoring N permissions.allow
entries … this workspace has not been trusted". Im bereinigten Snapshot tritt das nicht mehr auf;
erscheint die Meldung dennoch, ist der Snapshot nicht sauber – Abschnitt 1 prüfen.
Regeln:
- Arbeitsverzeichnis des Befehls = **Root-Verzeichnis** des Versuchs; geschrieben wird
ausschließlich ins Laufverzeichnis.
- Treten unerwartete Permission-Denials auf, die den Lauf behindern: die Denylist prüfen und die
Abweichung im Protokoll dokumentieren – **nicht** pauschal alle Prüfungen per
`--dangerously-skip-permissions` abschalten. Eine Änderung der Werkzeugkonfiguration ist eine
Änderung der Versuchsbedingung und gehört mit dem User abgestimmt.
- Optional `--max-budget-usd <betrag>` als harte Obergrenze setzen (nur mit `-p` wirksam) und den
Wert im Protokoll notieren. Das Flag arbeitet nur in USD – die **berichtete** Messgröße bleibt
der Tokenverbrauch. Anhaltspunkt: Der bisher aufwendigste Lauf verbrauchte 55.167.397 Tokens.
- Nach Abschluss des Background-Tasks: Endzeit mit `Get-Date -Format o` erfassen.
### 3. Ergebnis auswerten
`RawResult.json` im Laufverzeichnis lesen und defensiv parsen (Feldnamen können je nach Claude-Code-Version
leicht abweichen). Relevante Felder:
| Feld | Bedeutung |
|---|---|
| `is_error`, `subtype` | Lauf erfolgreich oder abgebrochen |
| `duration_ms`, `duration_api_ms` | Gesamt- und reine API-Dauer |
| `num_turns` | Anzahl Agent-Turns (Proxy für Werkzeugaktivität) |
| `total_cost_usd` | Kosten in USD – **wird nicht berichtet**, bleibt aber als Rohwert in der Datei |
| `usage.input_tokens`, `usage.output_tokens` | Tokens **nur des Hauptagenten** |
| `usage.cache_creation_input_tokens`, `usage.cache_read_input_tokens` | Cache-Tokens (getrennt ausweisen!) |
| `modelUsage` bzw. `model` | tatsächlich eingesetzte Modell-ID(s), Verbrauch **inklusive aller Subagenten-Ebenen** |
| `permission_denials` | verweigerte Werkzeugaufrufe – Anzahl und Aufschlüsselung nach `tool_name` |
| `subagent_stats` | gestartete Subagenten: `spawned`, `by_type`, `completed`, `failed`, `max_depth` |
| `session_id` | für spätere Transcript-Analyse (`claude --resume <id>`) |
| `result` | Abschlusstext des Agenten |
**`modelUsage` erfasst alle Verschachtelungsebenen – empirisch verifiziert.** Kontrolltest am
2026-08-25 gegen CLI 2.1.245: Eine erzwungene Kaskade (`max_depth: 2`, `spawned: 2`,
`spawned_by_subagents: 1`), bei der ausschließlich der **Enkel-Agent auf Tiefe 2** arbeitete –
er las 15 große Quelldateien, der mittlere Agent reichte nur durch, der Hauptagent las nichts:
| | Tokens |
|---|---:|
| `usage` (nur Hauptagent, 1 Turn) | 49.103 |
| `modelUsage` (gesamt) | **1.689.288** |
| Differenz = Subagenten | 1.640.185 (Faktor 34,4) |
Da die gesamte Leseleistung auf Tiefe 2 stattfand, belegt die Differenz, dass **auch
Sub-Subagenten in `modelUsage` einfließen**. Für die berichtete Aufwandsgröße „Tokens gesamt"
ist `modelUsage` daher die vollständige und einzig richtige Quelle.
**Subagenten-Transkripte werden nicht separat persistiert.** Im Projektverzeichnis liegt je Lauf
genau **eine** `.jsonl`-Datei, und Subagenten-Nachrichten erscheinen darin nicht als Sidechain.
Ihr Verbrauch ist deshalb ausschließlich über `modelUsage` sichtbar, nicht über das Transkript –
und die Summe der Transkript-Nachrichten ist **kein** gültiges Verbrauchsmaß (sie zählt Cache-Reads
über Turns hinweg mehrfach).
Zwei Auswertungsfallen:
- **`usage` erfasst ausschließlich den Hauptagenten.** Für den abrechnungsrelevanten
Gesamtverbrauch ist `modelUsage` über alle Modell-IDs zu summieren. In Iteration 01 standen
105.959 Output-Tokens in `usage` gegenüber 249.040 in `modelUsage`.
- **`duration_api_ms` kann die Wanduhrzeit übersteigen**, wenn Subagenten parallel laufen
(Iteration 01: 47:05 API gegenüber 31:31 Wanduhr). Das ist kein Widerspruch, sondern die
Summe nebenläufiger Anfragen – im Protokoll entsprechend einordnen.
**Pflichtprüfung: tatsächlich eingesetzte Modelle.** Nach jedem Lauf die Schlüssel von
`modelUsage` gegen das angeforderte Modell abgleichen. Zulässig sind nur die angeforderte
Modell-ID und `claude-haiku-4-5-*` (interne Hilfsaufrufe, wenige tausend Tokens). Taucht ein
weiteres Modell auf, ist die **Versuchsbedingung verletzt** – der Lauf ist im Protokoll als
solcher zu kennzeichnen und für Modellvergleiche unbrauchbar.
**`--model` steuert nur den Hauptagenten, nicht zwingend die Subagenten.** Belegt am 2026-08-25
(CLI 2.1.245, Lauf `fable5_builtin_ehigh_v3.7.0-15db`): Mit `--model claude-fable-5` und Modus
`builtin` liefen die 13 Subagenten auf **`claude-opus-5[1m]`** – dem Standardmodell aus
`~/.claude/settings.json`. Auf sie entfielen 136,7 von 150,3 Mio. Tokens (91 %).
| Kombination | Läufe | Modelle in `modelUsage` |
|---|---:|---|
| Sonnet / Opus / Fable + `solo` | 12 | nur das angeforderte Modell (+ Haiku) |
| Sonnet + `builtin` | 11 | nur `claude-sonnet-5` (+ Haiku) |
| **Fable + `builtin`** | **1** | **Fable + `claude-opus-5[1m]`** |
Sonnet und Opus werden an die Subagenten durchgereicht, Fable nicht; Claude Code fällt dann auf
die Sitzungsvorgabe zurück. **`--safe-mode` verhindert das nicht** – es deaktiviert
Customizations, nicht die Modellwahl. Im Modus `solo` tritt das Problem nicht auf, weil es keine
Subagenten gibt.
Bei Modus `builtin` oder `custom` daher **nie** den Flag-Wert allein ins Protokoll schreiben,
sondern die Modelle aus `modelUsage` mit ihrem jeweiligen Anteil ausweisen.
`permission_denials` ist eine **reguläre Messgröße** und immer auszuweisen, auch bei 0. Ein
hoher Wert bedeutet, dass die Werkzeugkonfiguration den Lauf eingeschränkt hat, und ist bei der
Interpretation der Ergebnisqualität zu berücksichtigen.
**Subagenten-Prompts sichern** (entfällt nur im Modus `solo`, dort gibt es keine). Die
vollständigen Prompts, mit denen der Hauptagent seine Subagenten beauftragt hat, stehen im
persistierten Session-Transkript unter
`%USERPROFILE%\.claude\projects\<projekt>\<session_id>.jsonl`. Das mitgelieferte Skript
extrahiert sie:
```powershell
python "<skillverzeichnis>\extract-subagenten.py" "<laufverzeichnis>"
```
Es schreibt `_meta\subagenten.md` (lesbar, mit vollständigem Prompt je Subagent) und
`_meta\subagenten.json` (maschinenlesbar). Erfasst werden Werkzeug (`Task`/`Agent`),
`subagent_type`, `description`, Hintergrund-Flag, Prompt-Länge und Länge des zurückgelieferten
Ergebnisses.
**Plausibilitätskontrolle:** Das Skript vergleicht die gefundene Anzahl mit
`subagent_stats.spawned` minus `spawned_by_subagents`. Im Haupttranskript stehen nämlich nur die
**direkt** vom Hauptagenten gestarteten Subagenten – von Subagenten gestartete (`max_depth` > 1)
liegen in deren eigenen Transkripten. Bei Abweichung setzt das Skript eine Warnung in
`subagenten.md`; dann ist die Ursache zu klären, bevor die Prompts ausgewertet werden.
**Warum das erhoben wird:** In V1b bestimmt der Agent selbst, wie er die Analyse zerlegt – über
alle bisherigen Läufe schwankte das zwischen 0 und 14 Subagenten mit völlig unterschiedlichen
Zuschnitten. Diese selbstgewählte Zerlegung ist die dominierende Störgröße der Versuchsreihe.
Erst die protokollierten Prompts machen sie als Datum auswertbar statt nur als Zahl sichtbar.
Für V2 (`custom`) sind sie zusätzlich der Vergleichsmaßstab: Sie zeigen, wie der Agent ohne
Vorgabe delegiert – gegenüber den vorformulierten Agenten aus `--agents`.
**Anforderungen auswerten** – der inhaltliche Ertrag des Laufs, nicht nur sein Aufwand:
```powershell
python "<skillverzeichnis>nalyse-anforderungen.py" "<laufverzeichnis>"
```
Das Skript parst das im Prompt vorgegebene Blockformat (`ID:`, `Typ:`, `Belege:`, `Status:` …)
aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` und schreibt `_metanforderungen.md`
(fertiger Protokollabschnitt) sowie `_metanforderungen.json` (maschinenlesbar). Erhoben werden:
- **Verteilung** über die drei Ebenen
- **Anforderungstypen** (funktional, Sicherheit, Daten, Schnittstelle …)
- **Belegqualität**: Anzahl der Belege, Aufteilung `PRIMÄR`/`SEKUNDÄR`/`KONTEXT`, Median je
Anforderung, Anteil mit mindestens einem Primärbeleg
- **Status**: belegt, `[HYPOTHESE]`, Workaround, Konsolidierungskandidaten
- **Regelkonformität** – geprüft wird gegen die Vorgaben des Prompts selbst:
Belegpflicht (jede Anforderung ≥ 1 Beleg), risikobasierte Priorisierung (Sicherheit,
Abrechnung, Berechtigungen brauchen `PRIMÄR` **oder** `[HYPOTHESE]`), Verifizierbarkeit
(Prüfidee vorhanden), Traceability (Tracelinks gesetzt)
**Warum das erhoben wird:** Die Anforderungsanzahl allein ist als Qualitätsmaß wertlos – sie
streute über Läufe gleicher Bedingung um Faktor 5,9. Belegdichte, Primärbelegquote und
Regelverstöße sind dagegen inhaltliche Größen und machen Läufe vergleichbar, deren Mengengerüst
weit auseinanderliegt. Die Regelkonformitätsprüfung deckt zudem auf, wo der Agent die eigenen
Vorgaben des Prompts verfehlt hat – ein Befund, der sich sonst nur durch Handlektüre ergäbe.
Der erzeugte Abschnitt wird **unverändert** als `## Gefundene Anforderungen` ins Protokoll
übernommen, zwischen `## Ergebnis` und den Vergleichs- bzw. Anmerkungsabschnitten.
Erzeugte Dateien: Inhalt von `<laufverzeichnis>\Ergebnisse\` auflisten. Zusätzlich prüfen,
ob das Root unverändert blieb: `git -C <root> status --porcelain` gegen `before.txt`
vergleichen (Nachher-Stand nach `$lauf\_metafter.txt`) – Abweichungen als Auffälligkeit
ins Protokoll. Beim Vergleich Zeilenenden
normalisieren (`before.txt` entsteht je nach Werkzeug mit CRLF, der Nachher-Stand mit LF),
sonst meldet ein naiver `diff` alle Zeilen als geändert.
### 4. Messprotokoll schreiben
Als `Protokoll.md` ins Laufverzeichnis, neben `RawResult.json` und `Stderr.log`.
Vorlage:
```markdown
# Messprotokoll – <Versuch> – Iteration <NN>
## Lauf
- **Prompt-Datei:** <relativer Pfad>
- **SHA-256 (Prompt):** <hash>
- **Startzeit:** <ISO 8601>
- **Endzeit:** <ISO 8601>
- **Dauer gesamt:** <hh:mm:ss> (API: <hh:mm:ss>)
- **Root-Verzeichnis:** <Pfad>
- **Codebasis-Commit:** <hash> (dirty: ja/nein)
- **Snapshot-Zustand:** <bereinigt von KI-Konfigurationen: ja/nein; Remote entkoppelt: ja/nein>
- **Prompt-Repo-Commit:** <hash>
## Werkzeugkonfiguration
- **Skill-Version:** <version aus dem Frontmatter dieses Skills>
- **Claude-Code-Version:** <version>
- **CLI-Pfad:** <aufgelöster Pfad zur claude.exe>
- **Modell (angefordert):** <Wert von `--model`>
- **Modelle (tatsächlich eingesetzt):** <alle Schlüssel aus `modelUsage` mit Tokenanteil>
- **Kontrolle Modell:** <bestanden | **verletzt**: nicht angefordertes Modell <ID> mit <N> Tokens>
- **Effort:** <low | medium | high | xhigh | max> (per `--effort` gesetzt; Gegenprobe im
Transkript-Feld `effort`)
- **Laufverzeichnis-ID:** `v<skillversion>-<id4>` aus dem Verzeichnisnamen
- **Ablage:** `<ModellID>/<Agentenmodus>/<Effort>/`
- **Parallele Läufe:** <nein | ja: welche Laufverzeichnisse liefen zeitgleich>
- **Agentenmodus:** <solo (V1) | builtin (V1b) | custom (V2)>; bei `custom` zusätzlich
Pfad und SHA-256 der Agentendefinitionen
- **Permission-Mode:** <acceptEdits | ...>
- **Toolfreigabe:** `--allowedTools <wörtlich>` / `--disallowedTools <wörtlich>`
- **Isolationsmechanismus:** <--safe-mode, --strict-mcp-config, ggf. --setting-sources>
- **MCP-Server / Agentendateien:** <keine – aus dem Snapshot entfernt, zusätzlich --safe-mode | Liste>
- **Subagenten:** <Anzahl und Typ aus `subagent_stats`, z. B. 8 × Explore, 0 fehlgeschlagen>
- **Verschachtelung:** `spawned` = <N>, davon `spawned_by_subagents` = <M>, `max_depth` = <D>.
Bei `max_depth` > 1 ausdrücklich vermerken – die Tokens der tieferen Ebenen sind in
„Tokens gesamt" enthalten, ihre Prompts jedoch **nicht** in `_meta\subagenten.md`
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | |
| Output-Tokens | <Wert> (davon N Thinking-Tokens aus `usage.output_tokens_details`) |
| Cache-Write-Tokens | |
| Cache-Read-Tokens | |
| Agent-Turns | |
### Gesamtlauf inkl. Subagenten (`modelUsage`, abrechnungsrelevant)
| Messgröße | <Modell-ID> | <weitere Modell-ID> | Summe |
|---|---:|---:|---:|
| Input-Tokens | | | |
| Output-Tokens | | | |
| Cache-Write-Tokens | | | |
| Cache-Read-Tokens | | | |
| **Tokens gesamt** | | | |
**Tokens gesamt: <Summe>** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Das ist die **berichtete Aufwandsgröße** der Versuchsreihe. `total_cost_usd` bleibt unberührt in
`RawResult.json` erhalten, wird aber nicht ins Protokoll übernommen: Token sind modell- und
preisunabhängig und bleiben damit über Preisänderungen und Modellwechsel hinweg vergleichbar.
## Gefundene Anforderungen
<unverändert aus `_metanforderungen.md` übernehmen – Verteilung, Typen, Belegqualität,
Status, Regelkonformität>
## Ergebnis
- **Status:** <erfolgreich | Fehler: ...>
- **Session-ID:** <id>
- **Permission-Denials:** <Anzahl> (<Aufschlüsselung nach Tool>; bei keinem Denial: 0).
Im Modus `solo` Denials auf `Task`/`Agent` **getrennt** ausweisen – sie sind die
Versuchsbedingung, keine Einschränkung.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = <Zahl> (bei `solo` muss 0 stehen,
sonst Fehlmessung)
- **Subagenten-Prompts:** <`_meta\subagenten.md`, N Aufrufe erfasst | entfällt (Modus solo)>
- **Erzeugte Dateien:** <Liste aus Ergebnisse\>
- **Root unverändert:** <ja | nein: welche Abweichungen>
- **Abschlusstext des Agenten:** siehe RawResult.json (`result`)
- **Anmerkungen/Auffälligkeiten:** <Beobachtungen, Abbrüche, manuelle Eingriffe>
```
### 5. Abschlussbericht an den User
Kurz zusammenfassen: Status, Dauer, Tokenverbrauch (inkl. Cache), Modell, Pfad des
Laufverzeichnisses und welche Dateien der Lauf erzeugt hat. Bei `is_error` oder leerem
Ergebnis: `Stderr.log` und `RawResult.json` zitieren, nicht spekulieren.
## Randbedingungen
- Niemals Messwerte schätzen oder erfinden – fehlt ein Feld im JSON, im Protokoll als
`nicht erfasst` eintragen.
- Prompt-Datei unverändert lassen; das Protokoll ist eine neue Datei.
- Läuft der Background-Task ungewöhnlich lange, User informieren statt abbrechen.
- **Am Codebasis-Root wird nichts verändert** – weder zur Vorbereitung noch zur Isolation noch
zur Nachbereitung. Ist das Root vor dem Lauf bereits `dirty`, den Zustand im Protokoll
festhalten und den User informieren, statt ihn stillschweigend zu bereinigen.
- **Der Codebasis-Snapshot ist eingefroren.** Kein `push`, kein `fetch`, kein Hinzufügen eines
Remotes, kein Commit im Codebasis-Repo. Soll der Snapshot geändert werden (etwa weil eine
weitere KI-Konfiguration auftaucht), ist das mit dem User abzustimmen, als eigener Commit
festzuschreiben und in allen betroffenen Protokollen als geänderte Versuchsbedingung zu
vermerken.
- **Werkzeugkonfiguration ist eine unabhängige Variable.** Weicht ein Lauf von der hier
festgelegten Standardkonfiguration ab (andere Flags, anderer Permission-Mode, zusätzliche
Tools), ist das im Protokoll unter „Werkzeugkonfiguration" wörtlich zu dokumentieren –
sonst sind die Läufe nicht vergleichbar.
## Versionierung
Die aktuelle Version steht im Frontmatter (`version:`) und **muss in jedes Protokoll** unter
„Werkzeugkonfiguration" als **Skill-Version** eingetragen werden. Nur so lässt sich später
zuordnen, unter welcher Fassung des Versuchsaufbaus eine Messung entstanden ist.
Schema (Semantic Versioning):
| Stelle | Bedeutung | Folge für die Vergleichbarkeit |
|---|---|---|
| **MAJOR** | Änderung der Versuchsbedingung – Flags, Toolfreigabe, Isolationsmechanismus, Codebasis-Snapshot | Läufe verschiedener MAJOR-Versionen sind **nicht** direkt vergleichbar |
| **MINOR** | Neue Pflichtschritte oder Messgrößen ohne Änderung der Versuchsbedingung | Läufe bleiben vergleichbar; die Protokolle werden reichhaltiger |
| **PATCH** | Fehlerkorrekturen am Ablauf, Dokumentation, Klarstellungen | Ohne Einfluss auf die Messung |
**Regel:** Wer den Skill ändert, erhöht die Version im Frontmatter und ergänzt eine Zeile in
der Historie unten – im selben Arbeitsschritt.
## Änderungshistorie
| Version | Änderung | Grund | Verwendet in |
|---|---|---|---|
| **1.0.0** | Ausgangsfassung: `--permission-mode acceptEdits`, kein Shell-Zugriff; Isolation durch Löschen der KI-Konfigurationsdateien im Root vor dem Lauf und `git restore` danach | Erstaufsetzung des Versuchsaufbaus | Lauf 1 (`01_Lauf_2026-08-25_1228`) |
| **2.0.0** | `--allowedTools "Bash" "PowerShell"` + 33er-Denylist für schreibende und bauende Kommandos. Isolation über **eingefrorenen Codebasis-Snapshot ohne KI-Konfigurationen** (Commit `79c1142`, Parent `89ccfd6`, GitHub-Remote entkoppelt), zusätzlich `--safe-mode` und `--strict-mcp-config`. Der destruktive Lösch-/Restore-Schritt pro Lauf entfällt. `permission_denials` und `subagent_stats` werden reguläre Messgrößen; Verbrauchstabelle trennt Hauptagent und Gesamtlauf. CLI-Pfad-Auflösung als eigener Schritt. | Lauf 1 erzeugte 36 Permission-Denials (32 × Bash, 4 × PowerShell); Shell-gestützte Verzeichnisinventuren fehlten dem Agenten. `--safe-mode` allein genügt nicht: Es unterdrückt das Vorladen von `CLAUDE.md`/`AGENTS.md`, verhindert aber nicht, dass der Agent sie mit Shell-Zugriff selbst liest – im Smoke-Test nachgewiesen. | Lauf 2 (`01_Lauf_2026-08-25_1349`, API-Abbruch) |
| **2.0.1** | `before.txt` wird leerwertsicher geschrieben (`Set-Content -Value (… \| Out-String)` statt Pipeline) | Bei sauberem Root schreibt `Set-Content` aus leerer Pipeline die Datei nicht und lässt alten Inhalt stehen; der Vorher/Nachher-Vergleich meldete dadurch eine Abweichung, die es nicht gab | Lauf 3 (`01_Lauf_2026-08-25_1429`) |
| **2.1.0** | **Modell wird vor jedem Lauf beim User erfragt** (Pflichtparameter, kein Default); Kurzformen `opus`/`sonnet`/`fable` untersagt | Das Modell ist eine unabhängige Variable und wurde bis dahin ad hoc gewählt. Kurzformen lösen auf das jeweils neueste Modell auf und verschieben die Versuchsbedingung über die Zeit. | Lauf 4 (`01_Lauf_2026-08-25_1505`) |
| **2.1.1** | Warnung zur Snapshot-Prüfung: Regex nicht vereinfachen, `Select-String` ist case-insensitiv; Beispiel-Falschtreffer dokumentiert | Ein verkürztes Muster sprach auf echte Produktdateien an (`ClaudeCodeChatModelClient.cs`, `GoogleGeminiChatModelClient.cs` – KI-Assistenz-Feature der ERP-Suite) und hätte beinahe einen Fehlabbruch ausgelöst | – |
| **3.0.0** | **Agentenmodus als Pflichtparameter** (`solo` / `builtin` / `custom`), vor jedem Lauf beim User erfragt. `solo` sperrt `Task`/`Agent`, `custom` übergibt vordefinierte Agenten per `--agents`. Neue Protokollfelder: Agentenmodus und Kontrolle `subagent_stats.spawned`. | Der Subagenten-Einsatz schwankte bei identischem Prompt zwischen 0 und 14 und war damit die dominierende Störgröße: Drei Läufe unter sonst identischer Bedingung ergaben 55 / 106 / 325 Anforderungen und 27,6 / 11,5 / 52,7 Mio. Tokens (Faktor 5,9 bzw. 4,6). Ohne Festlegung des Modus ist keine Bedingung sauber messbar. | ab Versuch 1 neu |
| **3.1.0** | **Parallelfähigkeit**: Laufverzeichnis sekundengenau plus Modus und 4-stellige Zufalls-ID; alle Steuerdateien nach `_meta\` im Laufverzeichnis statt in den gemeinsamen Scratchpad; neue Protokollfelder „Laufverzeichnis-ID" und „Parallele Läufe"; Abschnitt zu den messtechnischen Grenzen des Parallelbetriebs | Minutengenaue Namen kollidieren bei zwei Starts in derselben Minute, und geteilte Scratchpad-Dateien (`before.txt`, `combined_prompt.md`, Zeitstempel) hätten sich zwischen parallelen Läufen gegenseitig überschrieben. Nebeneffekt: Der exakt gesendete Prompt ist nun je Lauf archiviert. | – |
| **3.2.0** | Verzeichnisname enthält zusätzlich **Modell-Kurzform und Skill-Version**: `<NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_v<skillversion>-<id4>`. Solo-Modus sperrt zusätzlich **`Workflow`**. | Modell, Modus und Skill-Version sind die unabhängigen Variablen der Reihe und waren bisher nur im Protokoll sichtbar – im Namen verhindern sie, dass Läufe verschiedener Bedingungen gemeinsam ausgewertet werden. Die `Workflow`-Sperre schließt eine im Verifikationstest entdeckte Lücke: Nach der Sperre von `Task`/`Agent` versuchte der Agent, über `Workflow` zu orchestrieren. | ab Lauf 7 |
| **3.3.0** | **Subagenten-Prompts werden protokolliert.** Neues Skript `extract-subagenten.py` zieht aus dem Session-Transkript alle Subagenten-Aufrufe samt vollständigem Prompt nach `_meta\subagenten.md` / `.json`; neues Protokollfeld „Subagenten-Prompts". | Die selbstgewählte Zerlegung der Analyse ist die dominierende Störgröße (0 bis 14 Subagenten bei identischem Prompt) und war bisher nur als Zahl sichtbar. Mit den Prompts wird sie inhaltlich auswertbar und für V2 zum Vergleichsmaßstab gegenüber vorformulierten Agenten. | rückwirkend für alle Läufe angewandt |
| **3.4.0** | **Effort als dritter Pflichtparameter**: `--effort` wird vor jedem Lauf erfragt und im Protokoll geführt; Thinking-Tokens sind in der Verbrauchstabelle vorgesehen. | Der Denkaufwand ist eine unabhängige Variable, wurde aber bis dahin nur aus der Sitzung geerbt und nirgends dokumentiert. `RawResult.json` enthält **kein** `effort`-Feld – nachträglich ist er nur aus dem Session-Transkript belegbar. Rekonstruktion ergab: alle Läufe 1 bis B liefen auf `high`, die Bedingung war also konstant. | ab dem nächsten Lauf |
| **3.5.0** | **Berichtete Aufwandsgröße ist der Tokenverbrauch statt der USD-Kosten.** Verbrauchstabelle und alle Vergleiche führen „Tokens gesamt" (Input + Output + Cache-Write + Cache-Read über alle Modelle); `total_cost_usd` bleibt als Rohwert in `RawResult.json`, wird aber nicht mehr ins Protokoll übernommen. | USD-Beträge hängen an Preisliste und Modellwahl und veralten. Token sind die unmittelbare Verbrauchsgröße, bleiben über Preisänderungen und Modellwechsel hinweg vergleichbar und sind in der Arbeit ohne Währungsbezug zitierbar. | rückwirkend auf alle Protokolle angewandt |
| **3.6.0** | **Verschachtelte Subagenten dokumentiert und verifiziert.** Belegt, dass `modelUsage` auch Sub-Subagenten (Tiefe ≥ 2) erfasst; neues Protokollfeld „Verschachtelung" mit `spawned`, `spawned_by_subagents` und `max_depth`. Festgehalten, dass Subagenten-Transkripte nicht separat persistiert werden. | Bis dahin war unbelegt, ob tiefere Ebenen in die berichtete Tokensumme einfließen. Kontrolltest mit erzwungener Kaskade (Arbeit ausschließlich auf Tiefe 2): 49.103 Tokens im Hauptagenten gegenüber 1.689.288 in `modelUsage` – die Differenz stammt nachweislich vom Enkel-Agenten. | ab sofort |
| **3.7.0** | **Effort im Verzeichnisnamen**: `<NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_e<effort>_v<skillversion>-<id4>`, z. B. `_sonnet5_solo_ehigh_v3.7.0-a3f1`. | Das Schema entstand, als der Effort bei allen Läufen konstant `high` war. Mit dem ersten `max`-Block (Läufe P, Q) variiert er – gleichnamige Verzeichnisse hätten unterschiedliche Bedingungen bezeichnet und damit den Zweck des Schemas verfehlt. Der Effort ist zudem als möglicherweise stärkste Einflussgröße aufgefallen: Der `max`-Block erreichte die höchsten Thinking-Token-Werte der gesamten Reihe. | rückwirkend auf alle Laufverzeichnisse angewandt |
| **3.8.0** | **Pflichtprüfung der tatsächlich eingesetzten Modelle.** `modelUsage` ist nach jedem Lauf gegen das angeforderte Modell abzugleichen; neue Protokollfelder „Modell (angefordert)", „Modelle (tatsächlich eingesetzt)" und „Kontrolle Modell". | `--model` steuert nur den Hauptagenten. Im Lauf `fable5_builtin_ehigh_v3.7.0-15db` liefen die 13 Subagenten auf `claude-opus-5[1m]` statt auf Fable – 91 % des Verbrauchs entfielen auf ein nicht angefordertes Modell, und der Lauf wurde mit 150,3 Mio. Tokens der teuerste der Reihe. Ohne diese Prüfung bleibt die Bedingungsverletzung unbemerkt. | ab sofort; Gegenprüfung der 23 Vorläufe ergab keine weiteren Fälle |
| **3.9.0** | **Pflichtabschnitt „Gefundene Anforderungen" im Protokoll.** Neues Skript `analyse-anforderungen.py` wertet die erzeugten Anforderungen aus: Verteilung, Typen, Belegqualität (`PRIMÄR`/`SEKUNDÄR`/`KONTEXT`), Status, Konsolidierungskandidaten und **Regelkonformität gegen die Vorgaben des Prompts**. | Die Protokolle maßen bis dahin nur den Aufwand, nicht den Ertrag. Die reine Anforderungsanzahl taugt nicht als Qualitätsmaß (Streuung Faktor 5,9 bei gleicher Bedingung); Belegdichte und Regelverstöße sind inhaltliche Größen. Erste Anwendung deckte sofort Verstöße gegen die risikobasierte Priorisierung auf. | rückwirkend auf alle 24 Protokolle angewandt |
| **3.10.0** | **Bedingungen als Ordnerstruktur statt im Dateinamen.** Ablage unter `<ModellID>\<Agentenmodus>\<Effort>\`; der Verzeichnisname lautet wieder `<NN>_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>`. Neues Protokollfeld „Ablage". | Der Name wuchs mit jeder unabhängigen Variable und war mit fünf Bestandteilen kaum lesbar. Als Ordnerebenen sind die Bedingungen navigierbar, je Zelle unmittelbar abzählbar und um weitere Variablen erweiterbar, ohne bestehende Namen zu brechen. | rückwirkend auf alle 24 Läufe angewandt |
## Parallele Läufe
Mehrere Läufe dürfen gleichzeitig gestartet werden. Voraussetzung ist, dass **kein Zustand
geteilt** wird:
- **Verzeichnisname** ist sekundengenau und trägt Modus plus 4-stellige Zufalls-ID – zwei
gleichzeitige Starts können nicht kollidieren (Schritt 7 würfelt bei Kollision neu).
- **Alle Steuerdateien** (`combined_prompt.md`, `before.txt`, `after.txt`, Zeitstempel) liegen
in `_meta\` **im jeweiligen Laufverzeichnis**. Der gemeinsame Scratchpad wird für Laufdaten
**nicht** verwendet – dort würden parallele Läufe einander überschreiben.
- **Der Codebasis-Snapshot wird nur gelesen.** Beliebig viele Läufe dürfen ihn gleichzeitig
lesen. Die Vorher/Nachher-Prüfung bleibt gültig, weil kein Lauf schreibt.
- **Endeerkennung je Lauf** über das Erscheinen der eigenen `RawResult.json`, nicht über einen
gemeinsamen Marker.
**Messtechnische Einschränkung – im Protokoll zwingend vermerken.** Gleichzeitig laufende
Versuche konkurrieren um CPU, Netzwerk und API-Kontingent. Betroffen sind:
| Messgröße | Bei Parallelbetrieb |
|---|---|
| Wanduhrzeit | **verzerrt** – nicht mit seriellen Läufen vergleichbar |
| `duration_ms`, `duration_api_ms` | **verzerrt** |
| Tokenverbrauch, Anforderungsanzahl, Denials | unverzerrt |
Für Laufzeitvergleiche daher **seriell** messen. Parallelbetrieb eignet sich, um schnell
mehrere Datenpunkte für Umfang, Tokenverbrauch und Varianz zu sammeln. Das Feld
**„Parallele Läufe"** im Protokoll nennt die zeitgleich laufenden Laufverzeichnisse; steht dort
etwas anderes als `nein`, sind die Zeitangaben des Laufs nicht für Laufzeitvergleiche zu
verwenden.
## Zuordnung Versuch ↔ Agentenmodus
| Versuch | Modus | Bedeutung |
|---|---|---|
| **V1** – Baseline (Prompt-only) | `solo` | Ein Thread, ein Kontext; keine Subagenten |
| **V1b** – Baseline mit internen Agenten | `builtin` | Eingebaute Subagenten (`Explore`, `general-purpose`) |
| **V2** – Agentengestützt | `custom` | Nur vordefinierte, geprompte Agenten aus `--agents` |
**Einordnung der bisherigen Läufe:** Die Läufe 1–6 in `Versuche/Versuch_01/` liefen sämtlich mit
eingebauten Subagenten und gehören damit fachlich zu **V1b**, nicht zu V1. Sie belegen weiterhin
die Laufvarianz unter `builtin`, sind aber keine Baseline-Messung im Sinne der neuen Definition.
Bei der Auswertung entsprechend zuordnen.
@@ -0,0 +1,172 @@
# -*- coding: utf-8 -*-
"""Wertet die erzeugten Anforderungen eines Laufs aus und schreibt einen Protokollabschnitt.
Aufruf: python analyse-anforderungen.py <laufverzeichnis> [--print]
Erzeugt `<laufverzeichnis>/_meta/anforderungen.md` (der fertige Abschnitt) und
`<laufverzeichnis>/_meta/anforderungen.json` (maschinenlesbar).
Geparst wird das im Prompt vorgegebene Blockformat (`ID:`, `Typ:`, `Belege:`, `Status:` ...).
"""
import io, json, os, re, sys, collections
EBENEN = ('StRS', 'SyRS', 'SwRS')
# Anforderungen, fuer die der Prompt mindestens einen PRIMAER-Beleg verlangt
RISIKO = re.compile(r'sicherheit|abrechnung|fakturier|berechtigung|recht|zugriff|authentifiz|'
r'passwort|rolle|lizenz|steuer|zahlung|mahn', re.I)
def bloecke(pfad):
"""Zerlegt eine Anforderungsdatei in Bloecke ab jeder ID:-Zeile."""
if not os.path.exists(pfad):
return
text = io.open(pfad, encoding='utf-8').read()
teile = re.split(r'(?m)^ID:', text)
for t in teile[1:]:
yield 'ID:' + t
def feld(block, name):
m = re.search(r'(?m)^%s:[ \t]*(.*)$' % re.escape(name), block)
return m.group(1).strip() if m else ''
def analysiere(lauf):
erg = os.path.join(lauf, 'Ergebnisse')
anf = []
for eb in EBENEN:
for b in bloecke(os.path.join(erg, eb + '.md')):
aid = feld(b, 'ID')
if not aid:
continue
belege = re.findall(r'\[(PRIM\w*R|SEKUND\w*R|KONTEXT)\]', b)
norm = []
for x in belege:
norm.append('PRIMÄR' if x.startswith('PRIM')
else 'SEKUNDÄR' if x.startswith('SEKUND') else 'KONTEXT')
status = feld(b, 'Status')
anf.append(dict(
id=aid, ebene=eb, titel=feld(b, 'Titel'), typ=feld(b, 'Typ') or '(ohne)',
belege=norm, status=status,
hypothese=('HYPOTHESE' in status.upper()) or ('[HYPOTHESE]' in b),
workaround='workaround' in status.lower(),
tracelinks=feld(b, 'Tracelinks'),
konsolidierung=feld(b, 'Konsolidierung'),
pruefidee=feld(b, 'Prüfidee') or feld(b, 'Pruefidee'),
qm=feld(b, 'Qualitätsmerkmal'),
))
return anf
def de(n):
return '{:,}'.format(int(n)).replace(',', '.')
def pct(a, b):
if not b:
return '–'
return ('%.1f' % (100.0 * a / b)).replace('.', ',') + ' %'
def abschnitt(anf):
n = len(anf)
if not n:
return '## Gefundene Anforderungen\n\nKeine Anforderungen im vorgegebenen Format gefunden.\n'
je_ebene = collections.Counter(a['ebene'] for a in anf)
typen = collections.Counter(a['typ'] for a in anf)
bel = collections.Counter()
for a in anf:
bel.update(a['belege'])
bel_ges = sum(bel.values())
ohne_beleg = [a for a in anf if not a['belege']]
hyp = [a for a in anf if a['hypothese']]
work = [a for a in anf if a['workaround']]
ohne_trace = [a for a in anf if not a['tracelinks'] or a['tracelinks'].lower() in ('-', '–', 'keine')]
ohne_pruef = [a for a in anf if not a['pruefidee']]
kons = [a for a in anf if a['konsolidierung'] and a['konsolidierung'].lower() != 'nein']
mit_qm = [a for a in anf if a['qm']]
risiko = [a for a in anf if RISIKO.search(a['typ'] + ' ' + a['titel'])]
risiko_ungedeckt = [a for a in risiko if 'PRIMÄR' not in a['belege'] and not a['hypothese']]
zahlen = sorted(len(a['belege']) for a in anf)
median = zahlen[n // 2] if n % 2 else (zahlen[n // 2 - 1] + zahlen[n // 2]) / 2.0
z = ['## Gefundene Anforderungen', '',
'Maschinell aus `Ergebnisse\\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet '
'(Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.', '',
'### Verteilung über die Ebenen', '',
'| Ebene | Anzahl | Anteil |', '|---|---:|---:|']
for eb in EBENEN:
z.append('| %s | %d | %s |' % (eb, je_ebene.get(eb, 0), pct(je_ebene.get(eb, 0), n)))
z += ['| **Gesamt** | **%d** | 100 %% |' % n, '']
z += ['### Anforderungstypen', '', '| Typ | Anzahl | Anteil |', '|---|---:|---:|']
for t, c in typen.most_common(10):
z.append('| %s | %d | %s |' % (t, c, pct(c, n)))
if len(typen) > 10:
rest = sum(c for _, c in typen.most_common()[10:])
z.append('| (%d weitere) | %d | %s |' % (len(typen) - 10, rest, pct(rest, n)))
z.append('')
z += ['### Belegqualität', '', '| Messgröße | Wert |', '|---|---:|',
'| Belege gesamt | %s |' % de(bel_ges),
'| davon `PRIMÄR` | %s (%s) |' % (de(bel['PRIMÄR']), pct(bel['PRIMÄR'], bel_ges)),
'| davon `SEKUNDÄR` | %s (%s) |' % (de(bel['SEKUNDÄR']), pct(bel['SEKUNDÄR'], bel_ges)),
'| davon `KONTEXT` | %s (%s) |' % (de(bel['KONTEXT']), pct(bel['KONTEXT'], bel_ges)),
'| Belege je Anforderung (Median) | %s |' % str(median).replace('.', ','),
'| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | %d (%s) |'
% (sum(1 for a in anf if 'PRIMÄR' in a['belege']),
pct(sum(1 for a in anf if 'PRIMÄR' in a['belege']), n)),
'']
z += ['### Status', '', '| Kategorie | Anzahl | Anteil |', '|---|---:|---:|',
'| belegt | %d | %s |' % (n - len(hyp), pct(n - len(hyp), n)),
'| als `HYPOTHESE` gekennzeichnet | %d | %s |' % (len(hyp), pct(len(hyp), n)),
'| als Workaround vermerkt | %d | %s |' % (len(work), pct(len(work), n)),
'| Konsolidierungskandidaten | %d | %s |' % (len(kons), pct(len(kons), n)),
'| mit ISO-25010-Qualitätsmerkmal | %d | %s |' % (len(mit_qm), pct(len(mit_qm), n)),
'']
z += ['### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)', '',
'| Vorgabe | Ergebnis |', '|---|---|']
z.append('| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | %s |'
% ('**erfüllt** (0 Anforderungen ohne Beleg)' if not ohne_beleg
else '**verletzt** – %d ohne Beleg: %s' % (len(ohne_beleg),
', '.join(a['id'] for a in ohne_beleg[:8]) + (' …' if len(ohne_beleg) > 8 else ''))))
z.append('| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen '
'einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | %s |'
% ('**erfüllt** (%d risikorelevante Anforderungen, alle gedeckt)' % len(risiko)
if not risiko_ungedeckt
else '**verletzt** – %d von %d ungedeckt: %s' % (len(risiko_ungedeckt), len(risiko),
', '.join(a['id'] for a in risiko_ungedeckt[:8]) + (' …' if len(risiko_ungedeckt) > 8 else ''))))
z.append('| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | %s |'
% ('**erfüllt**' if not ohne_pruef
else '**verletzt** – %d ohne Prüfidee' % len(ohne_pruef)))
z.append('| **Traceability** – Verknüpfung zwischen den Ebenen | %d von %d mit Tracelinks (%s) |'
% (n - len(ohne_trace), n, pct(n - len(ohne_trace), n)))
z.append('')
return '\n'.join(z)
def main():
lauf = sys.argv[1]
anf = analysiere(lauf)
meta = os.path.join(lauf, '_meta')
os.makedirs(meta, exist_ok=True)
io.open(os.path.join(meta, 'anforderungen.json'), 'w', encoding='utf-8').write(
json.dumps(anf, indent=1, ensure_ascii=False))
text = abschnitt(anf)
io.open(os.path.join(meta, 'anforderungen.md'), 'w', encoding='utf-8').write(text + '\n')
if '--print' in sys.argv:
print(text)
else:
print('%s: %d Anforderungen ausgewertet -> _meta/anforderungen.md'
% (os.path.basename(os.path.normpath(lauf))[8:], len(anf)))
if __name__ == '__main__':
main()
@@ -0,0 +1,90 @@
"""Extrahiert Subagenten-Aufrufe (Prompt, Typ, Ergebnislaenge) aus dem persistierten
Session-Transkript eines Headless-Laufs und legt sie im Laufverzeichnis unter _meta ab.
Aufruf: python subagenten.py <laufverzeichnis> [<transkript-wurzel>]
Die Session-ID wird aus <laufverzeichnis>/RawResult.json gelesen.
"""
import io, json, os, sys, glob
lauf = sys.argv[1]
wurzel = sys.argv[2] if len(sys.argv) > 2 else os.path.expandvars(r'%USERPROFILE%\.claude\projects')
roh = json.load(io.open(os.path.join(lauf, 'RawResult.json'), encoding='utf-8-sig'))
sid = roh.get('session_id')
stats = roh.get('subagent_stats') or {}
gesamt = stats.get('spawned', 0)
verschachtelt = stats.get('spawned_by_subagents', 0)
# Im Haupttranskript stehen nur die direkt vom Hauptagenten gestarteten Subagenten.
# Von Subagenten gestartete liegen in deren eigenen Transkripten.
erwartet = gesamt - verschachtelt
treffer = glob.glob(os.path.join(wurzel, '*', sid + '.jsonl'))
if not treffer:
print('KEIN TRANSKRIPT gefunden fuer Session', sid)
sys.exit(1)
pfad = treffer[0]
aufrufe, ergebnisse = [], {}
for zeile in io.open(pfad, encoding='utf-8'):
try:
o = json.loads(zeile)
except Exception:
continue
cont = (o.get('message') or {}).get('content')
if not isinstance(cont, list):
continue
for c in cont:
if not isinstance(c, dict):
continue
if c.get('type') == 'tool_use' and c.get('name') in ('Task', 'Agent'):
ein = c.get('input') or {}
aufrufe.append({
'id': c.get('id'),
'werkzeug': c.get('name'),
'subagent_type': ein.get('subagent_type'),
'description': ein.get('description'),
'run_in_background': ein.get('run_in_background'),
'model': ein.get('model'),
'prompt': ein.get('prompt') or '',
})
elif c.get('type') == 'tool_result':
inhalt = c.get('content')
if isinstance(inhalt, list):
inhalt = ' '.join(str(x.get('text', '')) for x in inhalt if isinstance(x, dict))
ergebnisse[c.get('tool_use_id')] = len(str(inhalt or ''))
for a in aufrufe:
a['ergebnis_zeichen'] = ergebnisse.get(a['id'])
meta = os.path.join(lauf, '_meta')
os.makedirs(meta, exist_ok=True)
io.open(os.path.join(meta, 'subagenten.json'), 'w', encoding='utf-8').write(
json.dumps(aufrufe, indent=1, ensure_ascii=False))
md = ['# Subagenten-Aufrufe', '',
'Session `%s`, Transkript `%s`.' % (sid, os.path.basename(pfad)),
'',
'`subagent_stats`: **%s** Subagenten gesamt, davon **%s** von Subagenten gestartet '
'(max_depth %s). Direkt vom Hauptagenten erwartet: **%s**. Im Transkript gefunden: **%s**.'
% (gesamt, verschachtelt, stats.get('max_depth'), erwartet, len(aufrufe)), '']
if verschachtelt:
md += ['> Die %s von Subagenten gestarteten Aufrufe stehen in deren eigenen Transkripten und'
' sind hier **nicht** enthalten.' % verschachtelt, '']
if erwartet != len(aufrufe):
md += ['> **Abweichung** zwischen erwarteter und gefundener Anzahl.',
'> Ursache pruefen, bevor die Prompts ausgewertet werden.', '']
for i, a in enumerate(aufrufe, 1):
md += ['## %d. %s' % (i, a['description'] or '(ohne Beschreibung)'),
'',
'- **Werkzeug:** `%s` **Typ:** `%s` **Hintergrund:** %s'
% (a['werkzeug'], a['subagent_type'], a['run_in_background']),
'- **Prompt-Zeichen:** %d **Ergebnis-Zeichen:** %s'
% (len(a['prompt']), a['ergebnis_zeichen']),
'', '### Prompt', '', '```', a['prompt'].rstrip(), '```', '']
io.open(os.path.join(meta, 'subagenten.md'), 'w', encoding='utf-8').write('\n'.join(md))
print('Subagenten gefunden: %d (direkt erwartet: %s, gesamt: %s, davon verschachtelt: %s)' % (len(aufrufe), erwartet, gesamt, verschachtelt))
for a in aufrufe:
print(' - %-42s %s Prompt %6d Z. Ergebnis %s Z.'
% ((a['description'] or '')[:42], a['subagent_type'], len(a['prompt']), a['ergebnis_zeichen']))
print('geschrieben:', os.path.join(meta, 'subagenten.md'))
Submodule QuellCode/CentronERP added at 79c1142f48
+38 -14
View File
@@ -6,8 +6,8 @@
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-06-04
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger).
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
@@ -25,19 +25,25 @@ Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Scope und Validierung sind manuell vorgegeben):
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
1. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen.
2. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
3. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
4. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen.
5. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig.
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
@@ -55,14 +61,16 @@ Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Aussage: Das System soll <...>. (klare Soll-Aussage)
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String>
- [SEKUNDÄR] <...>
- [KONTEXT] <...>
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
@@ -73,7 +81,16 @@ Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Ergebnisstruktur (im aktuellen Arbeitsverzeichnis)
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
@@ -86,6 +103,8 @@ Ergebnisse/
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
@@ -96,6 +115,11 @@ Ergebnisse/
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
@@ -0,0 +1,21 @@
# Umbenennung der Laufverzeichnisse (2026-08-25)
Mit Skill-Version **3.2.0** enthalten Laufverzeichnisse Modell-Kurzform und Skill-Version:
`<NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_v<skillversion>-<id4>`
Die sechs vorher entstandenen Läufe wurden entsprechend umbenannt. Sekunden stammen aus der
im jeweiligen Protokoll dokumentierten Startzeit; die `<id4>` wurde nachträglich vergeben und
trägt keine Bedeutung. Alle Läufe liefen mit `claude-sonnet-5` und faktisch im Modus `builtin`.
| alt | neu |
|---|---|
| `01_Lauf_2026-08-25_1228` | `01_Lauf_2026-08-25_122905_sonnet5_builtin_v1.0.0-23e8` |
| `01_Lauf_2026-08-25_1349` | `01_Lauf_2026-08-25_134905_sonnet5_builtin_v2.0.0-8b0a` |
| `01_Lauf_2026-08-25_1429` | `01_Lauf_2026-08-25_142932_sonnet5_builtin_v2.0.1-5dc4` |
| `01_Lauf_2026-08-25_1505` | `01_Lauf_2026-08-25_150517_sonnet5_builtin_v2.1.0-acab` |
| `01_Lauf_2026-08-25_1535` | `01_Lauf_2026-08-25_153529_sonnet5_builtin_v2.1.1-db12` |
| `01_Lauf_2026-08-25_1635` | `01_Lauf_2026-08-25_163523_sonnet5_builtin_v2.1.1-26ea` |
**Unverändert geblieben:** die `RawResult.json` der Läufe. Sie enthalten teilweise noch die
alten Pfade in den vom Agenten geschriebenen Texten. Das ist Rohmessdatum und wird nicht
nachträglich verändert.
@@ -0,0 +1,37 @@
# Umbenennung der Laufverzeichnisse: Effort im Namen (2026-08-25)
Mit Skill-Version **3.7.0** enthält der Verzeichnisname zusätzlich den Effort:
`<NN>_Lauf_<yyyy-MM-dd_HHmmss>_<modell>_<modus>_e<effort>_v<skillversion>-<id4>`
Anlass war der erste Block mit `--effort max` (Läufe P und Q). Bis dahin lief alles auf
`high`, sodass der Effort im Namen entbehrlich schien. Die Stufe je Lauf wurde aus dem
jeweiligen Session-Transkript ausgelesen (`effort`-Feld je Nachricht, in jedem Lauf
eindeutig); `RawResult.json` enthält sie nicht.
| alt | neu |
|---|---|
| `01_Lauf_2026-08-25_122905_sonnet5_builtin_v1.0.0-23e8` | `01_Lauf_2026-08-25_122905_sonnet5_builtin_ehigh_v1.0.0-23e8` |
| `01_Lauf_2026-08-25_134905_sonnet5_builtin_v2.0.0-8b0a` | `01_Lauf_2026-08-25_134905_sonnet5_builtin_ehigh_v2.0.0-8b0a` |
| `01_Lauf_2026-08-25_142932_sonnet5_builtin_v2.0.1-5dc4` | `01_Lauf_2026-08-25_142932_sonnet5_builtin_ehigh_v2.0.1-5dc4` |
| `01_Lauf_2026-08-25_150517_sonnet5_builtin_v2.1.0-acab` | `01_Lauf_2026-08-25_150517_sonnet5_builtin_ehigh_v2.1.0-acab` |
| `01_Lauf_2026-08-25_153529_sonnet5_builtin_v2.1.1-db12` | `01_Lauf_2026-08-25_153529_sonnet5_builtin_ehigh_v2.1.1-db12` |
| `01_Lauf_2026-08-25_163523_sonnet5_builtin_v2.1.1-26ea` | `01_Lauf_2026-08-25_163523_sonnet5_builtin_ehigh_v2.1.1-26ea` |
| `01_Lauf_2026-08-25_173142_sonnet5_solo_v3.2.0-496c` | `01_Lauf_2026-08-25_173142_sonnet5_solo_ehigh_v3.2.0-496c` |
| `01_Lauf_2026-08-25_173143_sonnet5_solo_v3.2.0-2bc6` | `01_Lauf_2026-08-25_173143_sonnet5_solo_ehigh_v3.2.0-2bc6` |
| `01_Lauf_2026-08-25_180416_sonnet5_solo_v3.3.0-5851` | `01_Lauf_2026-08-25_180416_sonnet5_solo_ehigh_v3.3.0-5851` |
| `01_Lauf_2026-08-25_180417_sonnet5_solo_v3.3.0-664e` | `01_Lauf_2026-08-25_180417_sonnet5_solo_ehigh_v3.3.0-664e` |
| `01_Lauf_2026-08-25_180418_sonnet5_solo_v3.3.0-b676` | `01_Lauf_2026-08-25_180418_sonnet5_solo_ehigh_v3.3.0-b676` |
| `01_Lauf_2026-08-25_182941_sonnet5_builtin_v3.4.0-5b99` | `01_Lauf_2026-08-25_182941_sonnet5_builtin_ehigh_v3.4.0-5b99` |
| `01_Lauf_2026-08-25_182942_sonnet5_builtin_v3.4.0-176f` | `01_Lauf_2026-08-25_182942_sonnet5_builtin_ehigh_v3.4.0-176f` |
| `01_Lauf_2026-08-25_182943_sonnet5_builtin_v3.4.0-1407` | `01_Lauf_2026-08-25_182943_sonnet5_builtin_ehigh_v3.4.0-1407` |
| `01_Lauf_2026-08-25_182945_sonnet5_builtin_v3.4.0-1d0e` | `01_Lauf_2026-08-25_182945_sonnet5_builtin_ehigh_v3.4.0-1d0e` |
| `01_Lauf_2026-08-25_182946_sonnet5_builtin_v3.4.0-6bab` | `01_Lauf_2026-08-25_182946_sonnet5_builtin_ehigh_v3.4.0-6bab` |
| `01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603` | `01_Lauf_2026-08-25_195913_opus5_solo_ehigh_v3.6.0-2603` |
| `01_Lauf_2026-08-25_195915_opus5_solo_v3.6.0-6bfe` | `01_Lauf_2026-08-25_195915_opus5_solo_ehigh_v3.6.0-6bfe` |
| `01_Lauf_2026-08-25_195916_opus5_solo_v3.6.0-5070` | `01_Lauf_2026-08-25_195916_opus5_solo_ehigh_v3.6.0-5070` |
| `01_Lauf_2026-08-25_195917_opus5_solo_v3.6.0-26d8` | `01_Lauf_2026-08-25_195917_opus5_solo_ehigh_v3.6.0-26d8` |
| `01_Lauf_2026-08-25_195918_opus5_solo_v3.6.0-f63e` | `01_Lauf_2026-08-25_195918_opus5_solo_ehigh_v3.6.0-f63e` |
| `01_Lauf_2026-08-25_210903_fable5_solo_v3.6.0-7adf` | `01_Lauf_2026-08-25_210903_fable5_solo_emax_v3.6.0-7adf` |
| `01_Lauf_2026-08-25_210904_fable5_solo_v3.6.0-58d2` | `01_Lauf_2026-08-25_210904_fable5_solo_emax_v3.6.0-58d2` |
**Unverändert geblieben:** die `RawResult.json` der Läufe (Rohmessdaten).
@@ -0,0 +1,43 @@
# Umstellung auf Ordnerstruktur (2026-08-26)
Mit Skill-Version **3.10.0** tragen die Laufverzeichnisse Modell, Agentenmodus und Effort
nicht mehr im Namen, sondern als Ordnerebenen:
```
Versuche/Versuch_01/
01_Prompt.md
<ModellID>/<Agentenmodus>/<Effort>/01_Lauf_<yyyy-MM-dd_HHmmss>_v<skillversion>-<id4>/
```
Grund: Der Name war mit fünf Bestandteilen zu lang und wuchs mit jeder neuen unabhängigen
Variable weiter. Als Ordnerebenen sind die Bedingungen zugleich navigierbar und je Zelle
abzählbar. Der Verzeichnisname enthält nur noch Zeitstempel, Skill-Version und Zufalls-ID.
| alt | neu |
|---|---|
| `01_Lauf_2026-08-25_122905_sonnet5_builtin_ehigh_v1.0.0-23e8` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_122905_v1.0.0-23e8` |
| `01_Lauf_2026-08-25_134905_sonnet5_builtin_ehigh_v2.0.0-8b0a` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_134905_v2.0.0-8b0a` |
| `01_Lauf_2026-08-25_142932_sonnet5_builtin_ehigh_v2.0.1-5dc4` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_142932_v2.0.1-5dc4` |
| `01_Lauf_2026-08-25_150517_sonnet5_builtin_ehigh_v2.1.0-acab` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_150517_v2.1.0-acab` |
| `01_Lauf_2026-08-25_153529_sonnet5_builtin_ehigh_v2.1.1-db12` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_153529_v2.1.1-db12` |
| `01_Lauf_2026-08-25_163523_sonnet5_builtin_ehigh_v2.1.1-26ea` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_163523_v2.1.1-26ea` |
| `01_Lauf_2026-08-25_173142_sonnet5_solo_ehigh_v3.2.0-496c` | `claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173142_v3.2.0-496c` |
| `01_Lauf_2026-08-25_173143_sonnet5_solo_ehigh_v3.2.0-2bc6` | `claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173143_v3.2.0-2bc6` |
| `01_Lauf_2026-08-25_180416_sonnet5_solo_ehigh_v3.3.0-5851` | `claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180416_v3.3.0-5851` |
| `01_Lauf_2026-08-25_180417_sonnet5_solo_ehigh_v3.3.0-664e` | `claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180417_v3.3.0-664e` |
| `01_Lauf_2026-08-25_180418_sonnet5_solo_ehigh_v3.3.0-b676` | `claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180418_v3.3.0-b676` |
| `01_Lauf_2026-08-25_182941_sonnet5_builtin_ehigh_v3.4.0-5b99` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_182941_v3.4.0-5b99` |
| `01_Lauf_2026-08-25_182942_sonnet5_builtin_ehigh_v3.4.0-176f` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_182942_v3.4.0-176f` |
| `01_Lauf_2026-08-25_182943_sonnet5_builtin_ehigh_v3.4.0-1407` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_182943_v3.4.0-1407` |
| `01_Lauf_2026-08-25_182945_sonnet5_builtin_ehigh_v3.4.0-1d0e` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_182945_v3.4.0-1d0e` |
| `01_Lauf_2026-08-25_182946_sonnet5_builtin_ehigh_v3.4.0-6bab` | `claude-sonnet-5/builtin/high/01_Lauf_2026-08-25_182946_v3.4.0-6bab` |
| `01_Lauf_2026-08-25_195913_opus5_solo_ehigh_v3.6.0-2603` | `claude-opus-5/solo/high/01_Lauf_2026-08-25_195913_v3.6.0-2603` |
| `01_Lauf_2026-08-25_195915_opus5_solo_ehigh_v3.6.0-6bfe` | `claude-opus-5/solo/high/01_Lauf_2026-08-25_195915_v3.6.0-6bfe` |
| `01_Lauf_2026-08-25_195916_opus5_solo_ehigh_v3.6.0-5070` | `claude-opus-5/solo/high/01_Lauf_2026-08-25_195916_v3.6.0-5070` |
| `01_Lauf_2026-08-25_195917_opus5_solo_ehigh_v3.6.0-26d8` | `claude-opus-5/solo/high/01_Lauf_2026-08-25_195917_v3.6.0-26d8` |
| `01_Lauf_2026-08-25_195918_opus5_solo_ehigh_v3.6.0-f63e` | `claude-opus-5/solo/high/01_Lauf_2026-08-25_195918_v3.6.0-f63e` |
| `01_Lauf_2026-08-25_210903_fable5_solo_emax_v3.6.0-7adf` | `claude-fable-5/solo/max/01_Lauf_2026-08-25_210903_v3.6.0-7adf` |
| `01_Lauf_2026-08-25_210904_fable5_solo_emax_v3.6.0-58d2` | `claude-fable-5/solo/max/01_Lauf_2026-08-25_210904_v3.6.0-58d2` |
| `01_Lauf_2026-08-25_220735_fable5_builtin_ehigh_v3.7.0-15db` | `claude-fable-5/builtin/high/01_Lauf_2026-08-25_220735_v3.7.0-15db` |
**Unverändert geblieben:** die `RawResult.json` der Läufe (Rohmessdaten).
@@ -0,0 +1,121 @@
# Analysebericht
**Lauf:** V1 Baseline (Prompt-only), Iteration 01 — 2026-08-25
**Codebasis:** c-entron ERP-Suite, Commit 79c1142f48 (main), nur lesend analysiert.
**Methode:** RRE-Schritte 2–6 (Artefakterhebung, technische Analyse, semantische Interpretation, Formalisierung, Traceability); statische Analyse ohne Ausführung. Die technische Analyse wurde über 13 parallel arbeitende Explorationsdurchgänge (Werkzeug-interne Subagenten der Claude-Code-Standardausstattung, keine benutzerdefinierten Agentendateien, keine MCP-Server) über die Fachdomänen gefahren; Konsolidierung und Formalisierung erfolgten zentral.
---
## 1. Quantitativer Überblick der Codebasis
| Kennzahl | Wert | Quelle |
|---|---|---|
| Projekte in Centron.sln | 82 | Centron.sln |
| C#-Dateien (src) | 15.554 | Dateizählung |
| XAML-Dateien / Razor-Komponenten | 1.233 / 491 | Dateizählung |
| .NET-SDK / Version | 10.0.100 / 2.0.2611-alpha (Nerdbank) | global.json, version.json |
| Commits (2014–2026) | ~52.000 | git log |
| RPC-API-Endpunkte / REST-Aktionen | ~2.600 / 171 | ICentronRestService*, Centron.Controllers |
| NHibernate-Mappings / Entities / Tabellen+Views | 882 / 1.163 / ~807 | Centron.DAO/Entities |
| Migrationsskripte (aktuell/Legacy) | 764 / ~937+XML | Scripts-Verzeichnisse |
| Rechtekonstanten-Katalog | ~2.800 Zeilen (UserRightsConst) | Centron.WebServices.Core |
| Lizenz-GUIDs / ApplicationKinds | 159 / 48 | LicenseGuids.cs |
| Hintergrunddienste | ~34 | Centron.Host\HostedServices |
| E2E-Testklassen / Snapshots | 270 / 3.254 | tests\Centron.Tests.EndToEnd |
## 2. Modul-/Komponentenübersicht und Analysetiefe
Legende Analysetiefe: **T** = tief (Kernlogik gelesen, Regeln extrahiert), **S** = stichprobenhaft (Struktur + ausgewählte Dateien), **O** = nur Existenz/Überblick, **–** = nicht analysiert.
| Bereich | Wichtigste Artefakte | Tiefe | In Anforderungen |
|---|---|---|---|
| Belegwesen Verkauf (Sales/Receipts) | ReceiptBL (10k+ Z.), 12 SpecificLogics, DownPayment, ReceiptItem/Price/Account/BookingBL | T | SyRS-013…019, SwRS-016…030 |
| Vertragsabrechnung | AutomaticFacturaBL.Contracts, ReceiptContractHelperBL, ContractArticleReferenzes | T | SyRS-025 |
| Helpdesk/Tickets | HelpdeskBL/SearchBL/StatusBL, Escalation, Pattern, Checklists, TaskManager | T | SyRS-020…022 |
| Zeiterfassung/Abrechnung | HelpdeskTimer(BL/WebServiceBL/Signature), TimerBilling, ReceiptItemTimerBL | T | SyRS-023/024 |
| Einkauf/Lager/Logistik | Supplier-SpecificLogics, OrderSuggestionList, ArticleStock/Barcode/Inventory, Commission | T | SyRS-029…034 |
| RMA/Werkstatt | RmaBL (2k Z.), TicketRma-/SendBack-/SendForth-ViewModels | T | SyRS-035 |
| Finanzen | BookKeepingExport (DATEV ASCII/XML), BookKeepingImport, SEPA, Dunning/Opos, OnlineBanking, InvoiceZugferdBL, ebInterface | T | SyRS-016/017/019, 039–043 |
| Sicherheit/AuthN/AuthZ/Lizenz | Auth\*, TicketBL, AccessTokenBL, TwoFactor, AppRightsBL, LicenseManager, Kryptoklassen | T | SyRS-006…012, 055 |
| Nexus/Portal/Signatur | Index/Routing, PortAuth, ReceiptCart(+Release), SharedDocumentBL, WebReceipt, DsgvoBL, SelfCare | T | SyRS-026…028 |
| Webservice/Host/API | CentronHost, WcfBridge+Interceptors, Controllers, ConnectionManager, Deployment | T | SyRS-001…005, 049, 060 |
| Persistenz/Datenmodell | DAOFactory/DAOSession, Mappings, UserTypes, NamedQueries, ScriptEngine | T | SyRS-050, SwRS-061…065 |
| Stammdaten | AccountBL/Repository, Address/ContactPerson, ArticleBL, EmployeeArticle, NumberGroup, Country | T | SyRS-069 |
| Integrationen | EDI (SupplierEdi/Dispatcher), ITscope/EGIS/COP/Icecat, GLS/Shipcloud, docuFORM, finAPI, RMM/DocBee/TANSS/ES, Mail/Graph/EWS, Kalender-Sync, TAPI | T | SyRS-036…048 |
| Querschnitt/NFR | Logging, Telemetrie, Settings, Lokalisierung, Reporting, Suche, KI, Customizations, Tests, CI | T | SyRS-049…063 |
| Projekte/Planung | CrmProjectBL, TicketProject(+Webservice), Scheduler, Utilization | T | SyRS-062/065 |
| Kalender/MyDay/Termine | ScheduleBL, CalendarBL, MyDayBL(+Notifications), AppointmentRequests | T | SyRS-045/066/067 |
| Produktion | ProductionBL/OrderBL, Nexus-Werkeransicht | T | SyRS-064 |
| Restmodule | QM, Survey/Audit, Statistics-Module, TelekomDive, PayersAndCostCenter, PLM, ProjectPriceImport, Dashboard, MyCentron-Inspectors, ExpectedEvents, Devices, DocuBoard | S–T | SyRS-068 u. StRS/Hypothesen |
| WPF-UI-Fläche (1.233 XAML) | Views/ViewModels außerhalb der o. g. Regeln | S | punktuell als SEKUNDÄR-Belege |
| Dokumentenmanagement (FileManagement/Directories) | DocumentBL, Verzeichnisse | S | indirekt (StRS-027, SyRS-027) |
| ToDo/Notifications-Details, Chat, Mailings, SocialMedia, VideoPortal, Urls/WebLinks/Tags, TextModuleArea, CPra, DocumentationArea, MyCentron-Einzelseiten | BL-Ordner | O | nein (Lücke, s. u.) |
| Reports-Inhalte (FastReport-Definitionen), NamedQueryPool-Einzelqueries (371), pain.008-Generatklassen, übrige 11 FiBu-Formate im Detail | – | O/– | als Grenze ausgewiesen |
| VoucherManagement, CashBook, Provisionen (ReceiptProvisionBL nur gestreift), Mobile, IndexSearch-Dokumentteil, Outlook-AddIn-Innenleben, SupRemo, Buying/Storage-Legacy | – | O/– | nein (Lücke) |
| Centron.Controls / Controls.Preview, Centron.Common-Utilities (außer Krypto/Logging/Settings) | – | O | nein |
| tests\ (Inhalte einzelner E2E-Tests) | Infrastruktur gelesen, Fachtests nicht | S | SyRS-053 (Perf-Ziel) |
## 3. Ergebnisumfang
| Dokument | Anzahl Anforderungen | davon HYPOTHESE | davon „belegt; Workaround" |
|---|---|---|---|
| StRS.md | 27 | 1 (StRS-025, nur Zweck/Rechtsgrundlage) | 1 Abgrenzungsvermerk (Barbelege) |
| SyRS.md | 70 | 1 (SyRS-056, nur Abschaltbarkeit/Zweck) | mehrere Migrationshinweise in Aussagen |
| SwRS.md | 75 | 1 Teilmarkierung (SwRS-049 Rechtelücken-Intention) | 10 (SwRS-002, 018, 021, 022, 024, 030, 038, 045, 047, 051, 055, 064, 065, 069, 071 → 15 Kennzeichnungen) |
| Hypothesen.md | 20 Hypothesen (H-01…H-20) | — | — |
| Traceability.md | 71 Matrixzeilen | — | — |
| Glossar.md | ~120 Begriffe | — | — |
Belegklassifikation (Stichprobe über alle Anforderungen): jede Anforderung führt ≥1 Beleg; >90 % der Anforderungen besitzen mindestens einen PRIMÄR-Beleg; ausschließlich SEKUNDÄR/KONTEXT-gestützt sind nur SwRS-001 (Architekturmuster, KONTEXT-Doku + durchgängiges Namensmuster) sowie Teile von SyRS-058/060 (Ressourcen-/Pipeline-Zählungen) — dort ist die Aussage entsprechend zurückhaltend formuliert.
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Durchgeführt nach Abschluss der Formalisierung (manuell-systematisch über die ID-Register und Tracelink-Felder):
1. **Doppelte/mehrfach vergebene IDs:** keine. StRS-001…027, SyRS-001…070, SwRS-001…075 sind lückenlos und eindeutig vergeben (fortlaufende Vergabe, per Registerabgleich geprüft).
2. **Anforderungen ohne Beleg:** keine. Jede Anforderung führt mindestens einen klassifizierten Beleg mit Begründung; risikobehaftete Kategorien (Sicherheit, Abrechnung, Berechtigungen) führen durchgängig PRIMÄR-Belege.
3. **Tracelinks auf nicht existierende IDs:** Beim Check wurden **zwei fehlerhafte Abwärtsverweise gefunden und vor Abgabe korrigiert** (SyRS-063 verwies auf SwRS-063 [tatsächlich Migrations-Engine], SyRS-066 auf SwRS-062 [tatsächlich NamedQueries]; beide SyRS sind jetzt explizit „ohne eigene SwRS-Verfeinerung" markiert). Nach Korrektur: alle StRS→SyRS-, SyRS→StRS-, SyRS→SwRS- und SwRS→SyRS-Verweise zeigen auf existierende IDs; die Traceability-Matrix ist deckungsgleich mit den Tracelink-Feldern.
4. **Bidirektionalität:** Für jede in einem SyRS-Feld genannte SwRS-ID enthält die SwRS-Anforderung den Rückverweis (stichprobenartig vollständig gegengeprüft, 2 Korrekturen s. o.).
5. **Bekannte Einschränkung:** Zeilennummern in Belegen sind „ca."-Angaben aus dem Analysezeitpunkt (Commit 79c1142f48); bei künftigen Ständen sind Klasse/Methode maßgeblich.
## 5. Selbstbewertung
### 5.1 Vollständig vs. stichprobenhaft vs. nicht analysiert
- **Vollständig (regelextrahierend):** die 18 in Abschnitt 2 mit **T** markierten Kernbereiche — sie tragen die 172 Anforderungen.
- **Stichprobenhaft:** WPF-UI-Fläche (nur als SEKUNDÄR-Belegquelle und für client-only-Regeln), Restmodule (RMA tief, QM/Survey/PLM u. a. mittel), Dokumentenmanagement, Testinhalte.
- **Nicht analysiert:** VoucherManagement, CashBook, Provisionslogik im Detail, Chat/Mailings/SocialMedia/VideoPortal/TextModule/CPra/Urls/Tags, Mobile, Outlook-AddIn-Innenleben, SupRemo, Report-Definitionsinhalte, die 371 NamedQueries einzeln, 11 weitere FiBu-Exportformate im Detail, generierte SEPA-Klassen, Centron.Controls. Diese Bereiche sind im Anforderungs-Set entweder gar nicht oder nur als Systemkontext vertreten — das ist eine bekannte Abdeckungslücke, keine belegte Irrelevanz.
### 5.2 Wo der Beleg dünn ist
- **Icecat** (nur Settings, SEKUNDÄR) und **Lokalisierungs-/CI-Zahlen** (SEKUNDÄR-Zählungen).
- **Abwesenheitsbefunde** (kein Lockout, kein Passwortablauf, keine Mahngebühren, ungenutzte Rechte): methodisch als „Suche ohne Treffer" belegt — sie sollten in der Experten-Validierung bestätigt werden, da statische Suche Nebenpfade übersehen kann.
- **Intentionsfragen** sind konsequent in Hypothesen.md ausgelagert (20 Stück) statt als Anforderungen behauptet.
- **Client-only-Regeln** (Versand, Logistik-Settings, Produktion, zwei Helpdesk-Rechte): Ist-Verhalten PRIMÄR belegt, aber die Soll-Interpretation („serverseitig gewollt") ist Hypothese (H-03, H-12).
### 5.3 Zentrale Erkenntnisse für die Migrationsperspektive (Konsolidierungs-/Prüfschwerpunkte)
1. **Doppelstrukturen als Hauptkonsolidierungsfelder:** Alt-/Neu-Stammdaten (Kunden/Anschrif vs. Accounts, Dual-Write), zwei API-Stile, zwei Belegart-Kodierungen, zwei Signaturstrecken, zwei 2FA-Welten, vier Krypto-Klassen, dreifach implementierte Ticket-Sichtbarkeitsfilter, zwei Settings-Kataloge, Lese-Views vs. deutsche Schreibtabellen (10-Stellen-Pflegeregel).
2. **Sicherheits-Altlasten sind gut lokalisierbar** (SyRS-055/SwRS-014 als Ablösungskatalog) und stehen im Kontrast zu modernen Teilen (JWT-Validierung, Access-Tokens, Query-Level-RBAC).
3. **Die eigentliche Fachlogik ist serverseitig erstaunlich konsequent durchgesetzt** (Rechte in Queries, Belegpipeline, Zeiten-Sperren) — mit klar benannten Ausnahmen (Client-only-Fälle), die als explizite Migrationsanforderungen formuliert wurden.
4. **Gewachsene Zahlen-Toleranzen** (2,00 / 3,00 / 0,50 / 0,10 / 20) sind implizite Fachvorgaben und müssen fachlich bestätigt oder parametrisiert werden (H-17).
### 5.4 Empfohlener Nachschlag für Folge-Iterationen
1. **Fehlende Fachbereiche heben:** VoucherManagement, CashBook, Provisionen, Dokumentenmanagement/DMS-Kern, ToDo/Erinnerungswesen, Chat/Kommunikationsmodule — gleiche Methodik, geschätzt je 15–30 weitere Anforderungen.
2. **NamedQueryPool systematisch auswerten** (371 SQLs): dort stecken Reporting-/Buchhaltungsregeln, die bisher nur über ihre Aufrufer erfasst sind.
3. **Belegdruck/Reportinhalte** (FastReport-Definitionen in DB-Backups) für Layout-/Pflichtangaben-Anforderungen (z. B. Rechnungspflichtfelder).
4. **E2E-Testbestand als Anforderungsquelle** nutzen: 270 Tests + 3.254 Snapshots kodieren erwartetes Verhalten und eignen sich zur Verifikation der hier formalisierten Prüfideen.
5. **Hypothesenliste (H-01…H-20) mit Fachexperten schließen** — insbesondere H-01 (Telemetrie/Datenschutz), H-02/H-03 (Rechte-Lücken) und H-17 (Toleranzwerte) vor Architekturentscheidungen des Zielsystems.
6. **Delphi-Altanwendung** (nicht Teil dieser Codebasis) für die Barkassen-Funktion (H-08) und historische Datenkodierungen (UserTypes) hinzuziehen.
---
## 6. Dateiübersicht des Ergebnisses
```
Ergebnisse/
StRS.md 27 Stakeholder-Anforderungen
SyRS.md 70 System-Anforderungen (inkl. ISO-25010-Zuordnung der NFAs)
SwRS.md 75 Software-Anforderungen (Komponenten, Datenmodell, interne Regeln)
Traceability.md Forward-/Backward-Matrix StRS↔SyRS↔SwRS mit Artefaktbelegen
Hypothesen.md 20 Hypothesen mit offenen Validierungsfragen
Glossar.md ~120 Domänenbegriffe
Analysebericht.md dieses Dokument
```
@@ -0,0 +1,159 @@
# Glossar
Domänenbegriffe, wie sie in StRS/SyRS/SwRS verwendet werden. Technische Bezeichner (Klassen, Tabellen, Spalten) in Originalschreibweise. Quelle in Klammern, wo der Begriff kodifiziert ist.
## Organisations- und Identitätsbegriffe
| Begriff | Definition |
|---|---|
| **Mandant (Mandator)** | Rechtliche Firmeneinheit mit eigenen Bank-/SEPA-/FiBu-Daten. Mehrere Mandanten einer Installation teilen die Datenbank; getrennte Firmen laufen über getrennte Datenbanken/Sub-Web-Services. |
| **Filiale (Branch, Tabelle `Filiale`)** | Organisationseinheit unterhalb des Mandanten; steuert Nummernkreise, Rechte-Restriktionen („nur eigene Filiale"), Bundesland (Feiertage) und Auswertungssichten. |
| **AppUser (Tabelle `Sichbenu`)** | Internes Benutzerkonto, 1:1 mit einem Mitarbeiter (`Personal`) verknüpft. |
| **WebAccount** | Externes Portal-Benutzerkonto, an Ansprechpartner eines Kunden gebunden; eigenes Rechtesystem (`WebAccountRightsConst`). |
| **Kunden-Administrator** | WebAccount mit Web-Recht CUSTOMERADMINISTRATOR; verwaltet Portalbenutzer des eigenen Kunden selbst. |
| **Mitarbeiterartikel (EmployeeArticle)** | Dienstleistungsartikel, der einen Mitarbeiter für die Zeit-/Leistungsabrechnung repräsentiert (Stundensatz, Kostenstelle, Provision); definiert auch „eigene Zeit" (OWN_TIME_EDIT). |
| **Restriktives Recht (restricting right)** | Recht, dessen **Besitz** die Sicht einschränkt (z. B. „Tickets anzeigen – nur eigene"); Nichtbesitz bedeutet Vollzugriff (dokumentiert in CentronRights.md). |
| **Vertriebsgebiet (SalesArea)** | Mitarbeiter-Kunden-Zuordnung, die Beleg- und Ticketsichtbarkeit zusätzlich begrenzt. |
| **ConnectionTicket** | Serverseitige Sitzungskennung (40-Hex), gleitend gültig (Default 30 min); Grundlage der Concurrent-Lizenzzählung. |
| **Access-Token** | Persönliches API-Token für Maschinenzugriffe (Show-once, SHA-256-gespeichert, widerrufbar). |
| **Lizenz-GUID** | Kennung eines lizenzierbaren Moduls/Produkts (159 Stück); „Concurrent-User" = Zählung aktiver ConnectionTickets je Anmeldelizenz. |
## Belegwesen
| Begriff | Definition |
|---|---|
| **Beleg (Receipt/Asset)** | Oberbegriff für Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift, Vertrag sowie die Lieferantenpendants (Anfrage, Bestellung, Wareneingang, WE-Kalkulation/Lieferantenrechnung, Lieferantengutschrift). Kodiert in `CentronObjectKindNumeric`. |
| **Weiterverarbeitung (Forwarding)** | Erzeugen eines Folgebelegs aus einem Beleg entlang der festen Belegfluss-Matrix; Übernahme restmengenbasiert (Reference) oder vollständig (Copy). |
| **Belegversion** | Vollständiger Snapshot eines Belegs je Änderung (`*Versions`-Tabellen); Belege werden nie überschrieben. |
| **ReceiptState** | Belegzustand Active(1)/Completed(2)/Canceled(3); Completed wird restmengengetrieben automatisch gesetzt. |
| **Festschreibung (IsFixed)** | GoBD-Unveränderlichkeitskennzeichen einer Rechnung; unabhängig vom Belegzustand. |
| **Abholschein (PickupList)** | Rücknahmebeleg des Kunden (bestandserhöhend); Endpunkt der Kundenkette neben der Gutschrift. |
| **WE-Kalkulation (SupplierInvoice)** | Lieferantenrechnung/Einstandskalkulation zum Wareneingang; bei Spätbuchung der bestandswirksame Beleg. |
| **Spätbuchung (LateBooking, `SpaeteBuchung`)** | Prozessvariante, bei der erst die WE-Kalkulation (nicht der Wareneingang) den Bestand bucht. |
| **Direktlieferung (IsDirectDeliveryPossible)** | Lieferantenlieferung direkt an den Endkunden; überträgt Liefertermine in den Kundenauftrag. |
| **Anzahlungsrechnung / Schlussrechnung** | Rechnung mit Auftragsbezug über den konfigurierten Anzahlungsartikel; die Schlussrechnung zieht Anzahlungen als Negativpositionen ab. |
| **Kundenrabatt-Position** | Automatisch berechnete Belegposition (Kind CustomerDiscount), die den prozentualen Kundenrabatt als negativen Betrag abbildet. |
| **Positionsart (ReceiptItemArticlePositionKind)** | Kennzeichnung Default/Cargo/Alternativ/Optional/Informativ/„Auf Anfrage"/„Nach Aufwand"/„Keine Leistung"; nur Default/Cargo sind summenwirksam. |
| **Titelposition** | Gliederungsposition, die in der E-Rechnung ihre Unterpositionen aggregiert. |
| **Nummernkreis (NumberGroup)** | Konfigurierbarer Zähler je Belegart/Stammdatenart, filial-/mandantenabhängig aufgelöst; „InternalInvoice" = eigener Kreis für 0-€-Dienstleistungsrechnungen. |
| **Ursprung (`UrsprungI3D`/`UrsprungArt`)** | Positionsverweis auf die Quellposition der Belegkette (eigene Kodierung `ReceiptItemOrigin`). |
| **ConcurrencyControlGuid** | Optimistisches Sperrkennzeichen je Beleg; Abweichung beim Speichern signalisiert Parallelbearbeitung. |
## Preise/Konditionen
| Begriff | Definition |
|---|---|
| **Preisliste VK1–VK4** | Vier Verkaufspreisstufen am Artikel; Kundenzuordnung über `Customer.PriceList`. |
| **Kunden-Sonderpreis (CustomerSpecialPrice/AccountSpecialPrice)** | Zeitraumgültige Kondition je Kunde auf Artikel oder Warengruppe(+Unterwarengruppe); definiert auch den WebCart-Katalog. |
| **Vertrags-Sonderpreis (ContractSpecialPrice)** | Exklusive Preisregel eines Vertrags (5 Basen × Fest/Prozent; Werte invertiert gespeichert). |
| **Staffelpreis (ArticleVolumePrices)** | Mengenabhängige Preisstufen inkl. eigenem EK; vertraglich abschaltbar. |
| **Sondervereinbarung (SpecialAgreement)** | Projekt-/Rahmenkondition auf EK und/oder VK, kunden- oder belegartglobal. |
| **Mindestpreis (MinPrice)** | Untergrenze des Positionspreises; Unterschreitung nur mit Sonderrecht oder Zweitfreigabe. |
| **ActionPrice (`HerstellerArtikAktionspreis`)** | Befristeter Distributor-Aktionspreis; Anzeige im Preisspiegel, ohne automatische Belegpreiswirkung. |
| **EVP / Listenpreis** | Empfohlener Verkaufspreis bzw. Herstellerlistenpreis als Konditionsbasen. |
| **Preisspiegel** | Vergleichssicht der Einkaufsquellen (Lager-EK, Distributoren, Aktionspreise) je Artikel. |
## Steuern/Finanzen
| Begriff | Definition |
|---|---|
| **Steuerzone / Zielkategorie (AccountTargetKind)** | Klassifikation Inland/EU/Übersee/ReverseCharge/steuerfrei je Position; steuert Konto- und Steuerschlüsselwahl. |
| **Reverse Charge (§13b UStG)** | Steuerschuldumkehr; wirksam nur mit USt-IdNr. des Partners und Steuersatz 0 (Code „AE"). |
| **Erlös-/Aufwandskonto (ProfitAndLossAccount)** | Kontensatz je Artikel/Warengruppe/MwSt/Land mit acht Zielfeldern (Richtung × Zone). |
| **BU-Schlüssel** | DATEV-Buchungsschlüssel (Steuerschlüssel) aus dem MwSt-Stamm (`TaxCode`/`PurchaseTaxCode`). |
| **Splitbuchung** | Zerlegung eines Belegs in Buchungssätze je Konto/Steuersatz/Steuerschlüssel/Kostenstelle für den FiBu-Export. |
| **OPOS** | Offene-Posten-Verwaltung; „OPOS-Import" = Rückübernahme von FiBu-Zahlungen, „OPOS-Auszug" = Kontoauszugsreport ohne Mahnwirkung. |
| **Mahnstufe (DunningLevel)** | Eskalationsstufe 0–3 einer Rechnung; „Mahnsperre" = zeitfensterbasierter Ausschluss auf Kunden-/Rechnungsebene. |
| **SEPA-Mandat** | Lastschrifterlaubnis je Bankverbindung (Mandatsreferenz `AuthorizationNumber`, Unterschriftsdatum, Sequenztyp First/Recurrent/Single/Last, CORE/B2B). |
| **Gläubiger-ID (`SepaIdentificationNumber`)** | SEPA-Identifikation des Mandanten. |
| **Leitweg-ID** | B2G-Empfängerkennung; ihr Vorhandensein schaltet die E-Rechnung auf XRechnung-Konformität. |
| **ZUGFeRD / XRechnung** | Hybride PDF/A-3-Rechnung mit eingebettetem CII-XML bzw. deren B2G-Profil (EN 16931). |
| **ebInterface** | Österreichisches E-Rechnungsformat (implementiert, derzeit nicht angebunden). |
| **Festschreibungskennzeichen (Feld 114)** | DATEV-Feld „Buchung festschreiben"; standardmäßig 1. |
| **Kontingent (Contingent)** | Vertraglich vereinbartes Stunden- oder Geldbudget, das über Ausgleichspositionen verbraucht und bei Rücknahmebelegen zurückgerollt wird. |
| **Click-Vertrag / Klickabrechnung** | Abrechnung nach Gerätezählerständen (z. B. Druckseiten), Zähler u. a. via docuFORM. |
| **RMM-Artikel** | Vertragsposition, deren Menge aus einem RMM-System gemessen und mit Fix-/Mindest-/Höchstmengen verrechnet wird (Platzhalter `@@RMMArtikel@@`). |
| **Schweizer Rundung (CommercialRoundCH)** | 5-Rappen-Rundung des Bruttobetrags über eine Steuerkorrektur. |
## Service/Tickets/Zeiten
| Begriff | Definition |
|---|---|
| **Ticket/Helpdesk (Tabelle `hlpdsk_requests`)** | Servicevorgang mit konfigurierbarem Status-Stamm (`HelpdeskState`), Priorität, Kategorien, Bearbeitern und Verantwortlichem. |
| **Geschlossen-Status (HelpdeskClosedState)** | Der eine, per Einstellung bestimmte Status, der als „abgeschlossen" gilt; Setzen erfordert CLOSE_REQUEST. |
| **Fälligkeit (DueDate)** | Aus der Priorität und Geschäftszeiten berechneter Reaktionstermin; Änderung erfordert MATURITY_CHANGE und setzt die Eskalation zurück. |
| **Eskalationsstufe (EscalationLevel)** | Stufe 1–3 aus dem arbeitszeitbasierten Eskalationsmodell mit Empfängerkreisen je Stufe. |
| **Intern-Kennzeichnung (IsOnlyInternalVisible)** | Ticket-Flag, das Portalnutzern die Sicht entzieht. |
| **Freigabewesen (Portal-Tickets)** | Kundeninterner Genehmigungsschritt neuer Portal-Tickets; wartende Tickets tragen keinen Status. |
| **Timer / Helpdesk-Zeit (Tabelle `hlpdsk_timer`)** | Erfasste Servicezeit (Start/Stop, berechenbar-Flag, geplant-Flag) mit Belegpositions-Verweisen nach Abrechnung. |
| **IsAssignedToAsset** | „Zeit ist abgerechnet" (Auftrag, Lieferschein oder Rechnung) → Änderungssperre. |
| **Zeiten-Signatur** | Kundenunterschrift auf geleisteten Zeiten; einmalig, Entfernen nur mit DELETE_HELPDESK_SIGNATURE + Protokoll. |
| **Timer-Billing** | Abrechnungslauf, der berechenbare, unzugeordnete Zeiten in Belege überführt; optional mit automatischem Ticketabschluss. |
| **C-FLOW / TicketPattern** | Ticketvorlagen mit Vollausprägung (Kategorien, Checklisten, Formulare, Portal-Sichtbarkeit). |
| **Checkliste (CentronChecklist)** | Aus Vorlagen instanziierte Abarbeitungsliste am Ticket (8 Item-Status inkl. Misserfolgsarten). |
| **Taskmanagement** | Scheduler für wiederkehrende Serviceaufgaben inkl. automatischer Ticketerzeugung mit Vertretungsregelung. |
| **MyDay** | Persönliche Tagesrekonstruktion aus Terminen/Anrufen/Sessions mit abteilungsweiser Abschlusspflicht. |
| **ExpectedEvents** | Überwachung erwarteter wiederkehrender Kundenmeldungen (z. B. Backup-Reports) mit Textklassifikation. |
| **Stammblatt (MasterDataList, `GeraeteKopf`)** | Gerätelebenslauf-Akte (Seriennummernbezug), u. a. bei RMA/Verschrottung fortgeschrieben. |
| **Ticket-Fingerprint** | Gesalzener Hash über das Änderungsdatum eines Tickets zur Manipulationserkennung. |
## Lager/Logistik/RMA
| Begriff | Definition |
|---|---|
| **Hauptlager / Nebenlager (`Nebenlager`)** | Bestandsführende Lager; Hauptlager mit Kennung I3D=-1, Struktur Lager → Lagerort (`Lagerplatz`) → Lagerbereich. |
| **StockKind** | Lagertyp Default/RmaOwn/RmaCustomer/StockTransfer(Transit)/RepairAndLend. |
| **Seriennummer/Barcode** | Physische Einheit mit 25-Zustands-Lebenszyklus (`BarcodeState`); bestandsdefinierend für SN-Artikel (Zustände 1,2,8,9). |
| **SN-Pflicht (`Artik.BarcodeScanen`)** | Artikelflag „Seriennummern erforderlich"; schaltet die Bestandsdefinition auf SN-Zählung um. |
| **Exklusivbindung (BarcodeToPosition2)** | Eine SN ist zu jedem Zeitpunkt höchstens einer aktiven Belegposition zugeordnet. |
| **InIntake** | SN-Zustand „im Wareneingang erfasst, noch nicht gebucht" (nicht bestandswirksam). |
| **Zulauf (Intake)** | Materialisierter Cache bestellter/avisierter Mengen für den Bestellvorschlag. |
| **Bestellvorschlag (BVL)** | Automatische Bedarfsermittlung: Auftragsbedarf + Mindestbestand − Bestand − Zulauf, mit ABC-Lieferantenwahl. |
| **ABC-Lieferant (`ALieferantI3D`…)** | Priorisierte Bezugsquellen je Artikel für den Bestellvorschlag. |
| **Kommissionierung (QuantityPicked)** | Bereitstellung je Auftragsposition; bei SN-Artikeln zählt die gescannte SN-Menge; Teilkommissionierung über Packvorgänge (`PartialCommissionOrderState`). |
| **Inventurverlust (LostAtStocktaking)** | SN-Zustand für bei Inventurabschluss nicht gescannte Einheiten. |
| **Lagerumbuchung (TRANSFER_STOCK)** | Rechtepflichtige Bestandsverschiebung mit doppelter Log-Spur (`ARTIKlog`, `StockRebookLog`). |
| **Negativbuchung (RIGHT_NEGATIVBUCHUNG)** | Warenausgang in negativen Bestand; ohne Recht Vier-Augen-Fremdfreigabe. |
| **RMA (Eigen-/Kunden-/Fremdware)** | Werkstatt-/Reklamationsfall, zwingend ticketgebunden; Fremdware = Ware ohne eigene Beleghistorie (erhält neue SN im Sperrlager). |
| **Vorabtausch (AdvanceDeliveryList)** | Ersatzlieferung an den Kunden vor Abschluss der Lieferantenabwicklung (auch als Leihvariante). |
| **RmaForthAction** | Werkstattentscheidung je Position (1:1-Tausch, Fremdtausch, Reparatur, vor Ort, Verschrottung …). |
| **EK-Fortschreibung** | Gleitender Durchschnitt oder Letztpreis beim Wareneingang inkl. Fracht/Versicherung × Kalkulationsfaktor. |
## Portal/Web/Signatur
| Begriff | Definition |
|---|---|
| **Nexus** | Blazor-Weboberfläche (Mitarbeiter-ServiceBoard + Kundenportal in einer Anwendung, port-trennbar). |
| **ServiceBoard** | Mitarbeiter-Sicht in Nexus (Tickets, Kanban, Scheduler, Statistik). |
| **WebCart** | Kundenportal-Shop auf Basis der Kunden-Sonderpreise mit Prüfer/Besteller-Freigabewesen (`ReceiptCartState`). |
| **WebOffer / WebReceipt** | Tokenbasiert veröffentlichtes interaktives Angebot (`WebReceiptState`) mit Annahme-/Änderungs-/Ablehnfunktionen. |
| **SharedDocument („C-Sign")** | Tokenbasierter Signaturvorgang mit interner Freigaberunde, Signaturerfassung und automatischer Angebots-zu-Auftrags-Wandlung. |
| **OnlinePdfDocument** | Zweiter GUID-Signaturkanal für AVV-Verträge und SEPA-Mandate. |
| **SelfCare/WebForm** | Formularbaukasten inkl. anonymer öffentlicher Formularseite (`/webform/{Guid}`). |
| **WebAccountAccessType** | Portal-Belegsichtbarkeit je Belegart: Never/Always/UseWebAccountRight/OnlyBillable. |
| **Nexus-Notification** | Persistente Echtzeit-Benachrichtigung (Ticket-/Termin-/Erwähnungsereignisse). |
## Plattform/Betrieb
| Begriff | Definition |
|---|---|
| **I3D** | Universeller Integer-Surrogatschlüssel (IDENTITY) aller Kern-Entitäten. |
| **cvw_-View** | Schreibgeschützte Datenbank-Lesesicht für Listen/Suchen (CQRS-artiges Lesemodell). |
| **NamedQuery** | In `NamedQueryPool.xml` versioniertes SQL-Statement mit typisiertem Zugriff. |
| **ScriptMethod / DBUpdate** | Nummeriertes C#-Migrationsskript bzw. dessen Journaltabelle (Status 2 = ausgeführt). |
| **ManagedBackgroundService** | Basisklasse aller Hintergrunddienste (DB-Flag, Backoff, Lebenszeichen). |
| **ExecuteServices** | Konfigurationsschalter „diese Instanz führt die fachlichen Hintergrunddienste aus" (Single-Leader). |
| **Connection Manager** | Windows-Werkzeug für Dienstinstallation, Verbindungs-/AD-/2FA-Konfiguration und Sub-Web-Services. |
| **WebServiceConfig.xml** | Zentrale Dienstkonfiguration (teil-AES-verschlüsselt, SecretKey für Nexus-Push). |
| **Interceptor-Kette** | Priorisierte Querschnittspipeline der RPC-API (Logging→Auth→Telemetrie→Trimming). |
| **TrimResponse** | Clientgesteuerte Antwortreduktion (voll / nur I3D / leer). |
| **VMA / MailScanner** | „Virtual Mail Assistant": extern laufender Maildienst, der über konfigurierte Workflows Tickets erzeugt. |
| **EDI** | Elektronischer Belegaustausch mit Distributoren (Also, Herweck, Komsa, Alltron, OpenTrans, ZUGFeRD) direkt oder über Broker (ITscope, EGIS, Concerto). |
| **ITscope / EGIS / COP / Icecat** | Distributions-/Katalogplattformen: Handel+Deals (ITscope), Bestell-Broker (EGIS), SOAP-Katalog (COP), Produktcontent (Icecat). |
| **docuFORM** | MPS-Dienst für Druckerzählerstände (OAuth2/PKCE). |
| **finAPI** | PSD2-Bankaggregator für Kontoumsätze/Bankverbindungen. |
| **RiverDivo / RMM-Schnittstelle** | Eingehende Monitoring-Integration (Riverbird u. a.) mit Access-Key: Tickets, Kundensync, Dokumente. |
| **TAPI** | Telefonie-Anbindung über einen dedizierten TapiServer-Client mit SignalR-Ereignisverteilung. |
| **Telemetrie-Bucket** | 15-Minuten-Aggregat der Nutzungsmessung (API/KI/Module) für den Hersteller-Upload. |
| **DSGVO-Cleanup** | Rechte-/lizenzgeschützter Löschlauf mit standardisiertem Löschvermerk. |
| **Hardware-ID** | Geräte-Fingerprint für Lizenzbindung und Telemetrie (im Container per Umgebungsvariable setzbar). |
@@ -0,0 +1,130 @@
# Hypothesen
Sammlung aller mit `[HYPOTHESE]` markierten bzw. nicht eindeutig belegbaren Aussagen, jeweils mit offener Frage für die Experten-Validierung (Schritt 7 der RRE-Methodenkette). Sortiert nach Risiko/Relevanz.
---
## H-01 — Zweck und Rechtsgrundlage der Hersteller-Telemetrie
**Bezug:** StRS-025, SyRS-056, SwRS-067
**Belegte Fakten:** Upload personenbeziehbarer Nutzungsdaten (UserID, Hardware-Fingerprint, Methodenname, Lizenzart, CustomerNumber, DatabaseGuid) an „c-entron Office"; Client-Analytics mit Modulnutzungsdauer je Mitarbeiter. [PRIMÄR] HttpTelemetryUploadClient.cs Z.57–141; CentronAnalyticsManager.cs Z.54–127.
**Hypothese:** Zweck ist Lizenz-/Produktsteuerung des Herstellers; eine Betreiber-Abschaltmöglichkeit existiert nicht.
**Offene Frage:** Vertragliche Grundlage (AVV/EULA)? Ist ein Opt-out vorgesehen oder vorhanden (ggf. außerhalb des Codes, z. B. Firewall-Vorgabe)? Muss das Zielsystem eine Abschaltung/Anonymisierung anbieten?
## H-02 — Recht CHANGE_VISIBILITY ohne Durchsetzung
**Bezug:** SyRS-022/SwRS-031 (Umfeld)
**Belegte Fakten:** Recht 20400341 „Sichtbarkeit von Tickets bearbeiten" ist definiert und in CentronRights.md dokumentiert, wird aber weder in UI noch REST geprüft (UI-Checkbox ungefiltert, Endpunkt HelpdeskUpdateIsOnlyInternalVisible ohne Prüfung). [PRIMÄR, Abwesenheitsbefund] UserRightsConst.cs Z.1993; TicketDetailView.xaml Z.378–382; CentronRestService.Helpdesk.cs Z.652–656.
**Hypothese:** Die Durchsetzung war beabsichtigt und ist eine vergessene Implementierung (Soll-Anforderung ohne Ist).
**Offene Frage:** Soll das Ändern der Intern-Kennzeichnung im Zielsystem rechtepflichtig sein?
## H-03 — Nur clientseitig geprüfte Rechte (CREATE_HELPDESK_ONLY_OWN_BRANCH, MOVE_HELPDESK_TIMER)
**Bezug:** SyRS-020, SyRS-023
**Belegte Fakten:** Beide Rechte werden ausschließlich im WPF-Client ausgewertet; die Server-Pfade (HelpdeskBL.CheckUserRigths, MoveTimerToTicket) prüfen sie nicht. [PRIMÄR/SEKUNDÄR] TicketDetailViewModel.cs Z.1586–1588, 3713–3784.
**Hypothese:** Serverseitige Durchsetzung war intendiert (Muster der übrigen Rechte) und fehlt.
**Offene Frage:** Verbindlichkeit dieser Rechte im Zielsystem?
## H-04 — Inventur-Abschlussrecht CLOSE_INVENTORY ungenutzt
**Bezug:** SwRS-049
**Belegte Fakten:** Konstante 20400042 (und PRINT_INVENTORY_STATISTIC 20400046) definiert, keine Prüfstelle. [PRIMÄR, Abwesenheitsbefund] UserRightsConst.cs Z.1786–1799.
**Hypothese:** Der Inventurabschluss sollte rechtegeschützt sein.
**Offene Frage:** Rechtepflicht des Abschlusses im Zielsystem?
## H-05 — Vertragsende `null` („nobody knows")
**Bezug:** SyRS-025, SwRS-024
**Belegte Fakten:** GetContractLastDay liefert bei ContractEnd==null DateTime.MinValue; Kommentar: Verhalten wird nur „wie früher" repliziert, fachlich ungeklärt. [PRIMÄR+KONTEXT] AutomaticFacturaBL.Contracts.cs Z.1343–1353.
**Hypothese:** Verträge ohne Enddatum sollten wie automatisch verlängerte behandelt werden (unbegrenzt).
**Offene Frage:** Fachlich korrekte Semantik für Verträge ohne Enddatum?
## H-06 — ActionPrice bewusst keine Verkaufspreisquelle
**Bezug:** SyRS-015, SwRS-024
**Belegte Fakten:** Aktionspreise erscheinen laut Doku nur im Preisspiegel; die Belegpreisfindung greift nachweislich nicht darauf zu. [KONTEXT] actionprice-system.md; [PRIMÄR Gegenprobe] ReceiptItemPriceBL Z.154–387.
**Hypothese:** Informations-/Einkaufsentscheidungswerkzeug, bewusst ohne automatische Preiswirkung.
**Offene Frage:** Soll das Zielsystem Aktionspreise weiterhin nur anzeigen oder optional preiswirksam machen?
## H-07 — Mahnzinsen/-gebühren bewusst nicht implementiert
**Bezug:** SyRS-043
**Belegte Fakten:** Keine Berechnungslogik auffindbar; DATEV-Mahnfelder werden leer exportiert. [PRIMÄR, Abwesenheitsbefund] DunningBL/DatevAscii Felder 232–254.
**Hypothese:** Gebühren-/Zinsberechnung ist außerhalb des Produkts (FiBu/Steuerberater) angesiedelt.
**Offene Frage:** Anforderung an das Zielsystem (insb. §288 BGB-Verzugspauschalen)?
## H-08 — Barbelege: nicht migrierte Delphi-Funktion
**Bezug:** StRS-Abgrenzung, SwRS-016
**Belegte Fakten:** Datenstrukturen (IsCashAsset, Nummernkreise CashInvoice/CashOffer) existieren; Speichern blockiert mit „Aktuell werden leider noch keine Bar-Belege unterstützt." [PRIMÄR] ReceiptBL.cs Z.3763–3765.
**Hypothese:** Kassenfunktion lebt (noch) in der Delphi-Altanwendung; Migration geplant, nicht erfolgt.
**Offene Frage:** Ist eine Kassen-/Barverkaufsfunktion (inkl. TSE) Zielscope?
## H-09 — ebInterface (AT) vorbereitet, aber nicht angebunden
**Bezug:** SyRS-040
**Belegte Fakten:** Vollständige 4p3-Erzeugung ohne einen einzigen Aufrufer (nur auskommentierte Referenz). [PRIMÄR] EbInterfaceLogic.cs; BBGExport.cs Z.16.
**Hypothese:** Für den österreichischen Markt vorbereitet und nie produktiv geschaltet (bzw. abgelöst).
**Offene Frage:** AT-E-Rechnung im Zielscope (ebInterface vs. Peppol)?
## H-10 — Ticket-/Kampagnenprozess-Engine unfertig deaktiviert
**Bezug:** SwRS-069
**Belegte Fakten:** IsTicketProcessAvailable => Debugger.IsAttached; IsCampaignProcessAvailable => false; vollständige Fachlogik vorhanden. [PRIMÄR] ModuleFeatures.cs Z.26–27.
**Hypothese:** Feature wurde zurückgestellt; grafische Ticketprozesse sind eine geplante, nicht abgeschlossene Produktfunktion.
**Offene Frage:** Zielscope grafischer Ticket-Workflows?
## H-11 — Produktions-Wartezustand ausgespart
**Bezug:** SyRS-064
**Belegte Fakten:** Enum-Wert WaitingForOtherPartsToFinish auskommentiert („ignored for now"); keine Teilmengenrückmeldung. [PRIMÄR] ProductionOrderItemState.cs Z.15–18.
**Hypothese:** Abhängigkeitssteuerung zwischen Arbeitsschritten war geplant.
**Offene Frage:** Bedarf an Schrittabhängigkeiten/Teilmengen in der Zielfertigung?
## H-12 — Logistik-Einstellungen ohne Serverdurchsetzung
**Bezug:** SyRS-034 (Umfeld), SwRS-052
**Belegte Fakten:** IsTargetStorageMandatory, ClearStorageSpace, RebookStorage werden nur im WPF-Client ausgewertet. [PRIMÄR/SEKUNDÄR] LogisticSettingsBL.cs Z.26–112 + Client-ViewModels.
**Hypothese:** Serverseitige Durchsetzung ist beabsichtigtes Soll (analog übriger Pflichtregeln).
**Offene Frage:** Verbindlichkeitsgrad dieser Einstellungen im Zielsystem?
## H-13 — TradePool: mandantenübergreifender Marktpreis-Pool
**Bezug:** StRS-008 (Umfeld)
**Belegte Fakten:** Eigener XML-Import, eigene Benutzerverwaltung (TradeCustomerLogin mit CentronProductId), Min/Max-Spannenberechnung; keine Rechteprüfung; teils toter Code. [PRIMÄR] TradePoolBL.cs.
**Hypothese:** Herstellerbetriebener Preisvergleich zwischen c-entron-Kunden; Modul wenig gepflegt/auslaufend.
**Offene Frage:** Zielscope TradePool (weiterführen/abkündigen)?
## H-14 — WebOffer-Ablehnstatus „SendToCustomerDeclined" ungenutzt
**Bezug:** SyRS-027
**Belegte Fakten:** Enum-Wert 3 mit Kommentar „not used right now"; Acceptance-Seite enthält Platzhaltertexte („Bla bla bla..."). [PRIMÄR/SEKUNDÄR] SharedDocumentState.cs; SharedDocumentAcceptancePage.razor Z.35–36.
**Hypothese:** Kundenseitiger Ablehnpfad des Signaturprozesses ist unfertig.
**Offene Frage:** Soll der Kunde einen formalen Ablehnweg (mit Begründung) erhalten?
## H-15 — Filiallandbezug der Steuerwährung/Inlandsermittlung
**Bezug:** SyRS-016, SwRS-055
**Belegte Fakten:** GetInlandCountry nutzt nur das Standard-Mandantenland (TODO-Kommentar); ZUGFeRD-TaxCurrency stammt immer aus dem Standardland. [PRIMÄR+KONTEXT] CountryBL.cs Z.190–195; InvoiceZugferdBL.cs Z.296–301.
**Hypothese:** Für Filialen in anderen Ländern (AT/CH-Niederlassungen) ist die Steuerlogik unvollständig.
**Offene Frage:** Muss das Zielsystem filiallandabhängige Inlands-/Währungslogik unterstützen?
## H-16 — Freigabewesen-Tickets („Status null") als bewusstes Zustandsmodell
**Bezug:** SyRS-028, SwRS-034
**Belegte Fakten:** Portal-Tickets ohne Freigabe tragen HelpdeskState=null und werden intern ausgeblendet; Kommentar „normal flow of rejecting or accepting". [PRIMÄR] HelpdeskCustomerBL.cs Z.466–493.
**Hypothese:** „Kein Status" ist die bewusste Repräsentation „wartet auf Kundenfreigabe" (statt eigener Statuswert).
**Offene Frage:** Soll das Zielsystem dafür einen expliziten Status einführen?
## H-17 — Wertgrenzen/Heuristiken als Fachvorgaben
**Bezug:** SyRS-039, SyRS-040, SyRS-042
**Belegte Fakten (jeweils PRIMÄR):** FiBu-Differenzabbruch ≥ 2,00; ZUGFeRD-Selbstheilung < 3,00; Zahlungsabgleich ±0,50 (Einzel) und 0,10 (Erledigt-Toleranz); Teilsummen-Limit 20 Rechnungen.
**Hypothese:** Diese Konstanten sind gewachsene Praxiswerte, keine dokumentierten Fachvorgaben.
**Offene Frage:** Bestätigung/Parametrisierung der Toleranzen im Zielsystem?
## H-18 — Zwei parallele Signaturstrecken als Übergangszustand
**Bezug:** SyRS-027 (Konsolidierung)
**Belegte Fakten:** shareddocuments/{Token} (Belege) und contractmanagement?Guid= (AVV/SEPA) mit getrennten Datenmodellen (SharedDocument vs. OnlinePdfDocument, letzteres löscht nach Abschluss). [PRIMÄR] SharedDocumentBL.cs; DsgvoBL.cs Z.116–212.
**Hypothese:** Historisch getrennt entstanden; fachlich ein Prozess.
**Offene Frage:** Zusammenführung im Zielsystem (ein Signaturdienst)?
## H-19 — „C-Sign" als Produktname
**Bezug:** StRS-004
**Belegte Fakten:** Begriff nur in Commit-Messages (89ccfd650d, cf27c00580), nicht im Code. [KONTEXT]
**Hypothese:** Marketingname des SharedDocument-/WebOffer-Prozesses.
**Offene Frage:** Verbindliche Produkt-/Feature-Nomenklatur fürs Glossar.
## H-20 — SAP-Export als Individualentwicklung
**Bezug:** SyRS-039
**Belegte Fakten:** SAP-Exportformat nur für Lizenz-Kundennummer 13293 („marienhaus") bzw. intern sichtbar. [PRIMÄR] BookKeepingExportTypes.cs Z.62–84.
**Hypothese:** Kundenindividuelle Sonderlösung, nicht Produktstandard.
**Offene Frage:** Übernahme in das Zielsystem oder Sondervertrag?
---
### Hinweis zur risikobasierten Priorisierung
Alle Anforderungen der Kategorien Sicherheit, Abrechnung/Fakturierung und Berechtigungen in StRS/SyRS/SwRS führen mindestens einen PRIMÄR-Beleg und sind daher **nicht** als HYPOTHESE eingestuft; die vorstehenden Hypothesen betreffen Zweck-/Intentions- oder Abwesenheitsfragen, nicht die belegten Regeln selbst.
@@ -0,0 +1,583 @@
# StRS – Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (c-entron.NET WPF-Client, c-entron Web-Service, c-entron Nexus Web)
**Erstellt durch:** Reverse Requirements Engineering (statische Analyse der Codebasis, Stand Commit 79c1142f48, 2026-08-25)
**Normbezug:** ISO/IEC/IEEE 29148:2018 (Stakeholder-Ebene)
**Hinweis:** Alle Anforderungen sind aus Artefakten der Codebasis rückgewonnen ("Soll" = rekonstruiertes fachliches Soll, das das Ist-System implementiert). Jede Anforderung führt Belege mit Klassifikation `PRIMÄR`/`SEKUNDÄR`/`KONTEXT`. Nicht eindeutig belegbare Aussagen sind mit `[HYPOTHESE]` markiert.
---
## 1. Zweck und Systemkontext
Die Codebasis implementiert ein ERP-System für IT-Systemhäuser und Managed Service Provider im deutschsprachigen Markt: Handelsgeschäft (Angebot bis Gutschrift, Distributorenanbindung), Servicegeschäft (Tickets, Zeiterfassung, Verträge/wiederkehrende Abrechnung, RMA/Werkstatt) und Finanzprozesse (FiBu-Export, E-Rechnung, SEPA, Zahlungsabgleich, Mahnwesen), ergänzt um ein Kundenportal (Nexus) und ein Web-Shop-/Freigabemodul (WebCart).
### Stakeholder/Akteure (aus Artefakten abgeleitet)
| Akteur | Beleg |
|---|---|
| Interner Mitarbeiter (AppUser, verknüpft mit Personalstamm `Personal`) | `Centron.Entities\Entities\Administration\AppUser.cs` (Employee-Referenz) [PRIMÄR] |
| Administrator (Gruppe „Administratoren", I3D=6) | `Centron.BL\Administration\Rights\AppRightsBL.cs` Z.348–374 [PRIMÄR] |
| Endkunden-Benutzer (WebAccount am Ansprechpartner) | `Centron.Entities\Entities\Administration\Logins\WebAccount.cs` Z.6–35 [PRIMÄR] |
| Kunden-Administrator (Web-Recht CUSTOMERADMINISTRATOR, Self-Administration) | `src\nexus\CentronNexus\WebCart\WebCartAdminPage.razor` Z.3–4 [PRIMÄR] |
| Prüfer/Besteller im Kunden-Freigabewesen | `Centron.Interfaces\Sales\Receipts\ReceiptCartState.cs` [PRIMÄR] |
| Externer Signatur-Empfänger (tokenbasiert, ohne Login) | `Centron.BL\Administration\FileManagement\SharedDocumentBL.cs` Z.116–157 [PRIMÄR] |
| Betreiber/IT-Administrator (Connection Manager, WebServiceConfig) | `src\webservice\c-entron.misc.ConnectionManager\*` [PRIMÄR] |
| Hersteller (c-entron/NEXOWARE; Lizenzserver „c-entron Office", Telemetrie-Empfänger) | `src\webservice\Centron.Host\AspNetCore\Telemetry\HttpTelemetryUploadClient.cs` Z.57–74 [PRIMÄR] |
| Fremdsysteme (Distributoren-EDI, RMM/Riverbird, DocBee, TANSS, ElectronicSales, finAPI, GLS/Shipcloud, docuFORM, DATEV) | `src\apis\*`, `Centron.BL\EDI\*`, `Centron.BL\RiverDivo\*` [PRIMÄR] |
---
## 2. Anforderungen
```
ID: StRS-001
Titel: Zielsystem für IT-Systemhaus-/MSP-Geschäft
Ebene: StRS
Typ: funktional (Geschäftsziel)
Akteur: Systemhaus (Organisation)
Vorbedingung: –
Fakt: Die Codebasis vereint Handelsbelegwesen (Angebot/Auftrag/Lieferschein/Rechnung/Gutschrift, EDI-Distributoren), Servicegeschäft (Helpdesk-Tickets hlpdsk_requests, Zeiterfassung hlpdsk_timer, Verträge mit RMM-Mengenabrechnung), RMA/Werkstatt und Finanzprozesse in einer Lösung; Modul- und Lizenzkatalog (159 Lizenz-GUIDs, 48 ApplicationKinds) adressiert Systemhaus-Produkte (ServiceBoard, RMAWorkshop, OnlineBanking_FinApi, PLM …).
Aussage: Das System soll den durchgängigen Geschäftsbetrieb eines IT-Systemhauses/MSP abdecken: Vertrieb und Handel, Serviceerbringung mit Abrechnung, Reparaturabwicklung sowie vorbereitende Finanzbuchhaltung.
Ergebnis: Alle Kerngeschäftsprozesse laufen in einem integrierten System mit gemeinsamer Datenbasis (eine MSSQL-Datenbank).
Belege:
- [PRIMÄR] src\backend\Centron.Interfaces\CentronObjectKindNumeric.cs (Belegarten inkl. Helpdesk=10, Contract=22, RMA) – Begründung: Der zentrale Objektkatalog kodiert Handels-, Service- und Werkstattobjekte gleichrangig.
- [PRIMÄR] src\backend\Centron.Interfaces\Administration\Logins\LicenseGuids.cs (159 Modul-Lizenzen) – Begründung: Produktzuschnitt und Zielgruppe sind im Lizenzkatalog ablesbar.
- [KONTEXT] README.md (WebCart „for the customers of our customers") – Begründung: bestätigt B2B2C-Systemhaus-Kontext.
Prüfidee: Walkthrough: Ein Vorgang Angebot→Auftrag→Lieferschein→Rechnung→FiBu-Export sowie Ticket→Zeit→Abrechnung ist ohne Systemwechsel durchführbar.
Tracelinks: SyRS-001, SyRS-013, SyRS-020, SyRS-025, SyRS-035, SyRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Getrennte Identitäten für Mitarbeiter und Endkunden
Ebene: StRS
Typ: funktional
Akteur: Interner Mitarbeiter; Endkunden-Benutzer (WebAccount)
Vorbedingung: –
Fakt: Es existieren zwei getrennte Identitätstypen mit eigenen Entitäten (AppUser in Sichbenu; WebAccount am Ansprechpartner), eigenen Rechtesystemen (UserRightsConst vs. WebAccountRightsConst) und getrennten Login-Pfaden (/auth vs. /auth/customer); Benutzernamen teilen sich einen gemeinsamen Namensraum.
Aussage: Das System soll interne Mitarbeiter und externe Kundenbenutzer als getrennte Identitätstypen mit jeweils eigenem Berechtigungsmodell führen; ein Kundenbenutzer ist stets an einen Ansprechpartner eines Geschäftspartners gebunden.
Ergebnis: Kein Kundenbenutzer kann interne Funktionen nutzen; Mitarbeiter und Kundenkonten sind organisatorisch getrennt administrierbar.
Belege:
- [PRIMÄR] src\backend\Centron.Entities\Entities\Administration\Logins\WebAccount.cs Z.6–35 – Begründung: eigener Identitätstyp mit Kunden-/Kontaktbindung und eigener Rechteliste.
- [PRIMÄR] src\backend\Centron.BL\Administration\Logins\WebAccountBL.cs Z.637–650 (CheckDuplicateUsername gegen AppUser.Name) – Begründung: gemeinsamer Namensraum ist durchgesetzt.
- [PRIMÄR] src\backend\Centron.BL\Administration\Rights\AppRightsBL.cs Z.666–691 (HasWebAccountRight) – Begründung: getrenntes Rechtesystem.
Prüfidee: Test: WebAccount-Login gegen eine interne Funktion (z. B. Belegsuche) liefert Ablehnung („Web-Benutzer haben keine Berechtigung Belege einzusehen“) bzw. nur portalzulässige Daten.
Tracelinks: SyRS-006, SyRS-009, SyRS-010, SyRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-003
Titel: Durchgängiges, nachvollziehbares Belegwesen
Ebene: StRS
Typ: funktional
Akteur: Vertrieb/Innendienst
Vorbedingung: Kundenstammsatz vorhanden
Fakt: Der Belegfluss ist als fest verdrahteter Graph implementiert (Angebot→{Auftrag,LS,Rechnung}; Auftrag→{LS,Rechnung,Vertrag}; LS→{Abholschein,Rechnung}; Rechnung→{Gutschrift}; Vertrag→{Rechnung}); jede Änderung erzeugt eine neue Belegversion mit Snapshot; Restmengenlogik schließt Belege automatisch.
Aussage: Das System soll den Verkaufsprozess als lückenlose Belegkette mit kontrollierter Weiterverarbeitung, Versionierung jeder Änderung und automatischem Abschluss vollständig verarbeiteter Belege abbilden.
Ergebnis: Jeder Folgebeleg ist auf seinen Ursprung rückführbar; Mengen können nicht unbemerkt doppelt oder über den Ursprung hinaus verarbeitet werden.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Offers\OfferSpecificLogic.cs Z.314 u. a. (CanBeForwardedInto je Belegart) – Begründung: erlaubter Belegfluss ist Code-Matrix.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\ReceiptBL.cs Z.2462–2860 (ValidateReceiptForwarding) – Begründung: Weiterverarbeitung wird serverseitig validiert.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\ReceiptBL.cs Z.3081–3141 (CreateNewVersion) – Begründung: Versionierungspflicht.
Prüfidee: Testfälle: (a) unzulässige Weiterverarbeitung (z. B. Gutschrift→Auftrag) wird abgewiesen; (b) Reduktion einer bereits weiterverarbeiteten Menge wird abgewiesen; (c) vollständige Verarbeitung schließt den Beleg automatisch.
Tracelinks: SyRS-013, SyRS-014, SyRS-015, SyRS-017, SyRS-018, SyRS-038
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-004
Titel: Online-Angebotsannahme mit elektronischer Signatur und interner Freigabe
Ebene: StRS
Typ: funktional
Akteur: Kunde (tokenbasiert), Vertriebsmitarbeiter, interne Freigeber
Vorbedingung: Angebot existiert; Nexus-URL und Signaturdokument konfiguriert
Fakt: Der Prozess WebOffer (tokenbasiertes interaktives Angebot mit Mengen-/Positionsartänderung) mündet in SharedDocument-Signatur (Zeichnen/Tippen/Hochladen); vorgelagert ist eine Mitarbeiter-Freigaberunde (Acceptance, alle müssen zustimmen); die Kundensignatur eines Angebots wandelt es automatisch in einen Auftrag und der Button trägt die Beschriftung „Kostenpflichtig bestellen".
Aussage: Das System soll Angebote elektronisch zur Annahme bereitstellen, optional eine interne Mehr-Augen-Freigabe vor dem Kundenversand erzwingen, die rechtssichere Annahme (Buttonlösung, signiertes PDF-Gesamtdokument) protokollieren und aus der Annahme automatisch den Auftrag inklusive Folgeprozessen erzeugen.
Ergebnis: Angenommene Angebote werden ohne Medienbruch zu Aufträgen; der Signaturvorgang ist tokenbasiert, befristet, einmalig und vollständig protokolliert (SharedDocumentLog).
Belege:
- [PRIMÄR] src\backend\Centron.BL\Administration\FileManagement\SharedDocumentBL.cs Z.496–678 (SignSharedDocument inkl. ForwardOfferToOrderAndSave) – Begründung: Annahme→Auftrag ist durchgesetzte Logik.
- [PRIMÄR] src\nexus\CentronNexus\Office\SharedDocumentSignPage.razor Z.225 (ButtonText „Kostenpflichtig bestellen" bei OfferClass) – Begründung: Buttonlösung ist implementiert.
- [PRIMÄR] src\webservice\Centron.WebServices.Core\Entities\Administration\FileManagement\SharedDocuments\SharedDocumentState.cs Z.6–21 – Begründung: Freigabe- und Signaturzustände.
- [KONTEXT] Commit 89ccfd650d „C-Sign (WebOffer & Acceptance)" – Begründung: Produktname des Prozesses.
Prüfidee: E2E-Test: Angebot versenden → ein Freigeber lehnt ab → kein Kundenversand; alle stimmen zu → Kunde signiert → Auftrag existiert, signiertes PDF „_Signed.pdf" liegt im Belegverzeichnis, Log-Einträge vorhanden.
Tracelinks: SyRS-027
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Servicegeschäft über Tickets mit SLA-Steuerung
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Dispatcher, Kunde
Vorbedingung: Kunde vorhanden
Fakt: Tickets besitzen konfigurierbare Status, Prioritäten mit Fälligkeitsableitung (DueDateDelayInHours unter Berücksichtigung von Geschäftszeiten/Wochenenden), ein dreistufiges zeitgesteuertes Eskalationsmodell mit Empfängerkreisen sowie Kategorien/Typen, Checklisten, Vorlagen (C-FLOW/TicketPattern) und automatische Erzeugung (Taskmanagement, Belege, RMM, MailScanner, Portal).
Aussage: Das System soll Serviceanfragen als Tickets mit kundenkonfigurierbarem Lebenszyklus verwalten, Reaktions-/Fälligkeitstermine aus Prioritäten und Arbeitszeiten ableiten und überfällige Tickets stufenweise eskalieren.
Ergebnis: Fälligkeit und Eskalationsstufe jedes Tickets sind systemseitig berechnet und nachvollziehbar; Ticketentstehung ist aus mehreren Kanälen möglich.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\Support\HelpdeskBL.cs Z.786–827 (GetDueDateFromPriority) – Begründung: SLA-Terminableitung ist Code.
- [PRIMÄR] src\backend\Centron.BL\Sales\Support\Escalation\EscalationBL.cs Z.300–426, 913–929 – Begründung: dreistufige Eskalation wird durchgesetzt und persistiert.
- [PRIMÄR] src\backend\Centron.Entities\Entities\CustomerArea\Support\HelpdeskState.cs – Begründung: Status als konfigurierbare Stammdaten.
Prüfidee: Test: Priorität mit 4h-Frist, Büroschluss 17:00 → Ticket um 16:00 erzeugt → Fälligkeit am Folgearbeitstag; Eskalationslauf setzt Stufe 1..3 mit Benachrichtigung.
Tracelinks: SyRS-020, SyRS-021, SyRS-022, SyRS-051, SyRS-068
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Zeiterfassung mit revisionssicherer Leistungsabrechnung
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Abrechner, Kunde (Unterschrift)
Vorbedingung: Ticket vorhanden; Mitarbeiter besitzt Mitarbeiterartikel
Fakt: Zeiten (HelpdeskTimer) referenzieren nach Abrechnung die Belegposition (Order/DeliveryList/InvoiceAssetItemI3D) und sind dann weder änder-, lösch- noch verschiebbar; Kundenunterschriften auf Zeiten sind einmalig und nur mit Sonderrecht entfernbar (mit Protokoll); die Abrechnung (Timer-Billing) schließt geplante und bereits zugeordnete Zeiten aus; MyDay rekonstruiert Arbeitstage aus Fremdquellen und erzwingt abteilungsweise einen Tagesabschluss mit Eskalation an Teamleiter.
Aussage: Das System soll erbrachte Servicezeiten je Ticket erfassen, gegen Doppel- und Nachtragsmanipulation nach Abrechnung sperren, Kundenquittierung per Unterschrift unterstützen und die vollständige Tageserfassung organisatorisch durchsetzen.
Ergebnis: Abgerechnete Zeiten sind eingefroren; jede Zeit ist höchstens einmal fakturiert; Erfassungslücken werden erkannt und eskaliert.
Belege:
- [PRIMÄR] src\backend\Centron.BL\WebServices\Sales\Support\HelpdeskTimerWebServiceBL.cs Z.327–346, 591–608 – Begründung: Abrechnungs-Sperren sind mehrfach durchgesetzt.
- [PRIMÄR] src\backend\Centron.BL\Sales\Support\HelpdeskTimerSignatureBL.cs Z.132–206 – Begründung: Signatur- und Löschregeln mit Protokoll.
- [PRIMÄR] src\backend\Centron.BL\MyDay\MyDayNotificationsBL.cs Z.115–231 – Begründung: Tagesabschluss-Pflicht mit Eskalation.
Prüfidee: Test: Zeit einer fakturierten Position löschen/verschieben → Ablehnung; Timer-Billing derselben Zeit zweimal → zweiter Lauf enthält sie nicht.
Tracelinks: SyRS-023, SyRS-024, SyRS-066
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Vertragsgeschäft mit wiederkehrender, mengenbasierter Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Vertragsverwalter, Abrechnungslauf (System), RMM-System
Vorbedingung: Vertrag mit Abrechnungsparametern
Fakt: Verträge werden automatisch (vor-/nachschüssig, Intervalle mit Proration und Nachholung versäumter Perioden), nach Bedarf (Click/Kontingent) oder manuell abgerechnet; RMM-gemessene Mengen werden mit Vertragsmengen (Fix/Min/Max) verrechnet; bei nicht erreichbarem RMM-Dienst wird die Rechnungserstellung abgebrochen; Stunden-/Geldkontingente werden über Ausgleichspositionen verbraucht und bei Rücknahmebelegen zurückgerollt; nur die jeweils letzte Vertragsrechnung ist stornierbar.
Aussage: Das System soll wiederkehrende Leistungen vertragsbasiert automatisch fakturieren, dabei gemessene Nutzungsmengen (RMM, Zählerstände) mit vertraglichen Unter-/Obergrenzen verrechnen und die Abrechnungshistorie strikt sequenziell (LIFO-Storno) halten.
Ergebnis: Vertragsrechnungen entstehen ohne manuelle Positionierung; Nutzungsdaten fehlerhafter Quellen führen zu keiner (statt einer falschen) Rechnung.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\CustomerAssets\AutomaticFactura\AutomaticFacturaBL.Contracts.cs Z.1885–2019 (InvoicePeriodCalculate) – Begründung: Intervall-/Prorationslogik.
- [PRIMÄR] src\backend\Centron.Entities\Entities\Sales\CustomerAssets\Contracts\ContractArticleReferenzes.cs Z.27–39 – Begründung: Min-/Max-/Fixmengenregel.
- [PRIMÄR] src\backend\Centron.BL\WebServices\Sales\CustomerAssets\AutomaticFactura\AutomaticFacturaWebServiceBL.cs Z.721–823 (RMMServiceUnavailableException) – Begründung: Fail-Fast-Abrechnungsschutz.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Invoices\ReceiptInvoiceBL.cs Z.236–249 – Begründung: LIFO-Storno der Vertragsrechnungen.
Prüfidee: Test: Vertrag monatlich, 2 Monate nicht abgerechnet → ein Lauf erzeugt eine Rechnung über 2 Intervalle; RMM-Ausfall → Lauf bricht für diesen Vertrag mit Fehler ab.
Tracelinks: SyRS-025, SyRS-047, SyRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Einkauf mit Distributorenanbindung und Bedarfsermittlung
Ebene: StRS
Typ: funktional
Akteur: Einkäufer; Distributoren (EDI/API)
Vorbedingung: Lieferanten-/Artikelstamm gepflegt
Fakt: Bestellungen entstehen u. a. aus einem Bestellvorschlag (Bedarf = Auftragsbedarf + Mindestbestand − Bestand − Zulauf, mit ABC-Lieferantenlogik und Lieferantenkonditionen); Bestellungen gehen elektronisch an Distributoren (OpenTrans u. a., direkt oder über ITscope/EGIS/Concerto); Auftragsbestätigungen, Lieferavis und Rechnungen der Distributoren werden automatisch importiert (30-Minuten-Batch, Duplikat- und Fehlerdatei-Schutz); Katalog-/Preis-/Verfügbarkeitsdaten kommen aus ITscope/EGIS/COP/Importlisten, Produktcontent aus Icecat.
Aussage: Das System soll den Einkaufsprozess von der automatischen Bedarfsermittlung über die elektronische Bestellung bis zum automatisierten Import der Distributoren-Belege unterstützen.
Ergebnis: Bestellungen und Wareneingänge entstehen weitgehend ohne manuelle Doppelerfassung; auftragsbezogener Einkauf schreibt Bestell-/Buchungsmengen in den Kundenauftrag zurück.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Purchasing\OrderSuggestionList\OrderSuggestionListBL.cs Z.87–483 – Begründung: Bedarfsformel implementiert.
- [PRIMÄR] src\backend\Centron.BL\EDI\SupplierEDI\SupplierEdiBL.cs Z.1364–1414 – Begründung: automatischer Belegimport je Distributorformat.
- [PRIMÄR] src\backend\Centron.BL\EDI\EDIDispatcherBL.cs Z.56–288 – Begründung: elektronischer Bestellversand inkl. Broker.
Prüfidee: Test: Auftrag mit Bestellbedarf → Bestellvorschlag enthält Position mit korrekter Menge; simulierte Distributor-Antwortdatei erzeugt Wareneingangsbeleg genau einmal.
Tracelinks: SyRS-029, SyRS-030, SyRS-036, SyRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Bestandsführung mit Seriennummern-Rückverfolgbarkeit
Ebene: StRS
Typ: funktional
Akteur: Lagerist, Logistik, Inventurteam
Vorbedingung: Artikel-/Lagerstamm gepflegt
Fakt: Seriennummernpflichtige Artikel werden bestandsseitig über die Anzahl ihrer Seriennummern in definierten Zuständen geführt (statt Mengenzähler); jede Seriennummer ist exklusiv genau einem aktiven Beleg zugeordnet und trägt Zustands- und Historienmodell (25 Zustände, BarcodeHistory, ARTIKlog); Warenausgang bucht beim Lieferschein, Rücknahmen beim Abholschein/Gutschrift; Inventur korrigiert Bestände lagerweise mit Verlustkennzeichnung nicht gescannter Seriennummern; Umbuchungen sind rechte- und protokollpflichtig, Negativbuchungen im Warenausgang genehmigungspflichtig (Vier-Augen-Fremdanmeldung).
Aussage: Das System soll Lagerbestände mengen- und seriennummerngenau führen, jede physische Einheit lückenlos über ihren Lebenszyklus verfolgen und Bestandskorrekturen (Inventur, Umbuchung, Negativbuchung) kontrolliert und auditierbar abwickeln.
Ergebnis: Zu jeder Seriennummer ist Standort/Belegbindung/Historie jederzeit ermittelbar; Bestandsabweichungen entstehen nur über protokollierte Vorgänge.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Administration\Scripts\ScriptMethods\Scripts\ScriptMethod11482.cs Z.25–54 (cvw_ArticleCount/cvw_BarcodeCount) – Begründung: SN-basierte Bestandsdefinition ist DB-seitig verankert.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Internal\ReceiptBarcodeBL.cs Z.554–879 – Begründung: Exklusivbindung SN↔Belegposition.
- [PRIMÄR] src\backend\Centron.BL\Warehousing\InventoryManagement\InventoryBL.cs Z.797–944 (CloseStorages) – Begründung: Inventurabschluss als kontrollierte Bestandskorrektur.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Internal\ReceiptArticleBookingBL.cs Z.357–424 – Begründung: Vier-Augen-Regel Negativbuchung.
Prüfidee: Test: SN in Lieferschein → zweite Zuordnung in anderem Beleg wird abgewiesen; Inventur ohne Scan einer SN → Status „Inventurverlust"; Umbuchung ohne Recht TRANSFER_STOCK → Ablehnung.
Tracelinks: SyRS-031, SyRS-032, SyRS-033, SyRS-034
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-010
Titel: RMA-/Werkstattprozess für Eigen-, Kunden- und Fremdware
Ebene: StRS
Typ: funktional
Akteur: Service-Annahme, Werkstatt, Lieferant, Kunde
Vorbedingung: RMA-Lager konfiguriert
Fakt: RMA-Fälle sind zwingend an ein Ticket gebunden, unterscheiden Eigen-/Kunden-/Fremdware mit unterschiedlicher Bestands-/Belegbehandlung, durchlaufen einen 19-stufigen Positionsstatus (Rücksendung, Vorabtausch, Leihgerät, Gutschrift, Verschrottung …) mit LIFO-Storno und dürfen erst geschlossen werden, wenn für jede Kundenposition ein Ausgangsbeleg (Lieferschein oder Gutschrift) existiert; Tausch-Seriennummern werden in die Ursprungsrechnung rückgebucht (Gewährleistungsnachweis).
Aussage: Das System soll Reklamations- und Werkstattfälle vollständig abbilden – von der Annahme (inkl. Fremdware ohne eigene Beleghistorie) über Lieferantenrücksendung und Ersatzlieferung bis zu Kundenbeleg und Abschluss – und dabei Bestands-, Seriennummern- und Gewährleistungsdaten konsistent halten.
Ergebnis: Kein RMA-Abschluss ohne Kundenbeleg; jede Werkstattaktion ist über Nummernkreise (RMA/Rücksendung/Reparatureingang) und Historien nachvollziehbar.
Belege:
- [PRIMÄR] src\backend\Centron.BL\CustomerArea\RmaBL.cs Z.352–353, 932–1258, 1916–1996 – Begründung: Ticketpflicht, Statusfluss, Lagerlogik je RMA-Art.
- [PRIMÄR] src\centron\Centron.WPF.UI\Modules\Helpdesk\TicketDetails\Rma\TicketRmaViewModel.cs Z.855–921 (CanClose/CanStornoHistory) – Begründung: Abschluss-/Stornoregeln.
- [PRIMÄR] src\backend\Centron.BL\CustomerArea\RmaBL.cs Z.142–183 (RebookForChange) – Begründung: Gewährleistungs-Rückbuchung der Tausch-SN.
Prüfidee: Test: Kunden-RMA ohne Lieferschein/Gutschrift schließen → Ablehnung; Fremdware-Position erzeugt neue SN im RMA-Kundenlager; Storno eines Schritts mit Folgeschritt → Ablehnung.
Tracelinks: SyRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Vorbereitende Finanzbuchhaltung und Zahlungsverkehr
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung, Steuerberater/DATEV, Bank
Vorbedingung: Kontenrahmen/Steuersätze gepflegt
Fakt: Belege werden in 13 FiBu-Formate exportiert (führend DATEV ASCII EXTF 700 und DATEV-XML-Online) mit Splitbuchungen je Konto/Steuerschlüssel/Kostenstelle; Zahlungsrückläufe werden als OPOS-Import verarbeitet; SEPA-Lastschriften (bis pain.008.001.08) mit vollständiger Mandatsverwaltung; Bankumsätze via finAPI mit dreistufigem automatischem Zahlungsabgleich; Mahnwesen mit 3 Stufen und Mahnsperren; exportierte Rechnungen sind storno-gesperrt.
Aussage: Das System soll die vorbereitende Buchhaltung vollständig bedienen: steuerlich korrekte Buchungssatz-Erzeugung für Fremd-FiBu-Systeme, Lastschrifteinzug mit SEPA-Mandaten, automatischen Zahlungseingangsabgleich und gestuftes Mahnwesen.
Ergebnis: Rechnungswesen-Daten fließen ohne Doppelerfassung an die FiBu; offene Posten werden systemgestützt ausgeglichen und gemahnt.
Belege:
- [PRIMÄR] src\backend\Centron.Gateway\DataExchange\BookKeeping\DatevAscii\BookKeepingExportDatevAscii.cs Z.551–1033 – Begründung: DATEV-Buchungssatz vollständig implementiert.
- [PRIMÄR] src\backend\Centron.Gateway\DataExchange\PaymentTransactions\Sepa\SepaFileGeneratorV2.cs Z.32–364 – Begründung: SEPA pain.008.001.08 mit Mandatslogik.
- [PRIMÄR] src\backend\Centron.BL\Finances\OnlineBanking\OnlineBankingAccountTransactionsBL.cs Z.581–1086 – Begründung: automatischer Zahlungsabgleich.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Invoices\Dunning\DunningRunBL.cs Z.200–315 – Begründung: 3-stufiges Mahnwesen.
Prüfidee: Abnahmetest je Teilprozess: DATEV-Datei gegen DATEV-Prüfprogramm; SEPA-Datei gegen Bank-Validator; Zahlungsabgleich mit exaktem/abweichendem Betrag (<0,50 €) und Sammelzahlung.
Tracelinks: SyRS-016, SyRS-019, SyRS-039, SyRS-040, SyRS-041, SyRS-042, SyRS-043
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Kundenportal mit Self-Service und Beschaffungs-Freigabewesen
Ebene: StRS
Typ: funktional
Akteur: Endkunden-Benutzer, Kunden-Administrator
Vorbedingung: WebAccount vorhanden; Lizenz (CentronNexus/WebCart2)
Fakt: Das Nexus-Kundenportal bietet Ticketanlage/-einsicht (inkl. optionalem kundeninternem Freigabewesen für neue Tickets), Beleg-/Vertragseinsicht (pro Belegart konfigurierbar), Dokumente, Formulare und einen Shop (WebCart), dessen Artikelumfang ausschließlich aus den Kunden-Sonderpreisen stammt und dessen Bestellungen ein zweistufiges Prüfer/Besteller-Freigabewesen durchlaufen; Kunden-Administratoren verwalten Portalbenutzer und deren Rechte selbst; Mandantentrennung ist serverseitig in den Abfragen erzwungen.
Aussage: Das System soll Endkunden einen abgesicherten Selbstbedienungszugang zu ihren Service- und Handelsvorgängen bieten, einschließlich eines kundenindividuellen Beschaffungskatalogs mit unternehmensinternem Genehmigungsworkflow und delegierter Benutzerverwaltung.
Ergebnis: Kunden sehen ausschließlich eigene Daten; Shop-Bestellungen erreichen das ERP erst nach kundeninterner Freigabe als regulärer Auftrag.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\ReceiptCartBL.cs Z.128–241 (Sonderpreis-Katalog) – Begründung: Katalogumfang ist durchgesetzt.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\ReceiptCartReleaseSystemBL.cs Z.65–283 – Begründung: Freigabewesen serverseitig.
- [PRIMÄR] src\backend\Centron.BL\Sales\Support\HelpdeskSearchBL.cs Z.536–565 – Begründung: serverseitige Mandantentrennung im Portal.
- [PRIMÄR] src\backend\Centron.Interfaces\CustomerPortal\WebAccountAccessType.cs – Begründung: konfigurierbare Belegsichtbarkeit.
Prüfidee: Test: WebAccount ohne Sonderpreise sieht leeren Shop; Bestellfreigabe ohne WEBRIGHT_WEBCART2_ORDER_CART → Ablehnung; Ticket eines fremden Kunden per ID abrufen → „nicht gefunden".
Tracelinks: SyRS-026, SyRS-028, SyRS-010
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Feingranulares Berechtigungssystem mit einschränkenden Rechten
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, alle Benutzer
Vorbedingung: Benutzer in Rechtegruppen
Fakt: Rechte sind hierarchische Integer-Konstanten (~2.800 Zeilen UserRightsConst), werden ausschließlich über Gruppen zugewiesen (Sichmemb/Sichtrus) und serverseitig geprüft – auch als Datenfilter in Abfragen (nur eigene Kunden/Tickets, nur eigene Filiale, Vertriebsgebiete); es existiert die dokumentierte Sonderklasse „restricting rights" (Besitz schränkt ein); Rechtevergaben werden vollständig auditiert (AppRightLog); die Admin-Gruppe ist gegen Löschung/Fehlkonfiguration geschützt.
Aussage: Das System soll Funktions- und Datenzugriff rollenbasiert steuern, wobei Datenrestriktionen (eigene Datensätze, eigene Filiale, Vertriebsgebiet) serverseitig in den Abfragen und nicht nur in der Oberfläche wirken, und jede Änderung an Berechtigungen revisionssicher protokollieren.
Ergebnis: Zugriffsentscheidungen sind clientunabhängig durchgesetzt und nachvollziehbar; ein Aussperren aller Administratoren ist verhindert.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Administration\Rights\AppRightsBL.cs Z.644–664, 762–857 – Begründung: zentrale Prüfung + Audit.
- [PRIMÄR] src\backend\Centron.BL\Accounts\AccountSearchBL.cs Z.331–344; src\backend\Centron.BL\Sales\Support\HelpdeskSearchBL.cs Z.324–391 – Begründung: Query-Level-Durchsetzung.
- [KONTEXT] CentronRights.md (Konzept „restricting right") – Begründung: dokumentierte invertierte Semantik.
Prüfidee: Test je restriktivem Recht: Nutzer mit SHOW_HELPDESK_ONLY_OWN erhält per API (nicht nur UI) ausschließlich eigene Tickets.
Tracelinks: SyRS-006, SyRS-007, SyRS-008, SyRS-009, SyRS-010, SyRS-011, SyRS-055
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: Modul- und Concurrent-User-Lizenzierung
Ebene: StRS
Typ: nicht-funktional (Produktsteuerung)
Akteur: Hersteller, Betreiber
Vorbedingung: Signierte Lizenzdatei
Fakt: 159 Lizenz-GUIDs steuern Modul-Freischaltung serverseitig in der BL (nicht nur UI); Anmeldelizenzen werden concurrent gegen aktive Session-Tickets gezählt (PerUserAndPerMachine bzw. PerUser); die Lizenz ist kryptographisch signiert, hardwaregebunden und harte Startvoraussetzung des Web-Service; Modulsichtbarkeit im Client = Recht × Lizenz (ModuleRegistration).
Aussage: Das System soll Funktionsumfang und Nutzerzahl über signierte, hardwaregebundene Lizenzen steuern; Lizenzprüfungen müssen serverseitig erfolgen und die gleichzeitige Nutzung begrenzen.
Ergebnis: Nicht lizenzierte Module sind auch per API nicht nutzbar; Überschreitung der Nutzerzahl verhindert weitere Anmeldungen (LicenseMaximumReached).
Belege:
- [PRIMÄR] src\backend\Centron.BL\Administration\Licensing\LicenseManager.cs Z.219–302 – Begründung: Start-Gate + Concurrent-Zählung.
- [PRIMÄR] src\backend\Centron.DAO\Repositories\Administration\Logins\TicketRepository.cs Z.95–119 – Begründung: Zählmodi.
- [PRIMÄR] src\centron\Centron.WPF.UI\Modules\ModuleRegistration.cs Z.486–889 – Begründung: Recht×Lizenz-Freischaltmuster.
Prüfidee: Test: Lizenz-Count n, n+1 parallele Logins → letzter abgelehnt; BL-Aufruf eines unlizenzierten Moduls → LicenseNotFound.
Tracelinks: SyRS-012, SyRS-007
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Mehrfilial- und Mehrfirmenbetrieb
Ebene: StRS
Typ: funktional
Akteur: Organisation mit Filialen/Mandanten
Vorbedingung: Filial-/Mandantenstamm
Fakt: Filiale (Filiale) und Mandant (Mandator) sind Querschnittsdimensionen: Nummernkreise je Filiale/Mandant, Belegrechte „nur eigene Filiale" serverseitig erzwungen, Management-Info/Bankauszüge filialbeschränkbar, Buchhaltungs-/Bankdaten je Mandant; echte Mandantentrennung mehrerer Firmen erfolgt über getrennte Datenbanken/Sub-Web-Services (Connection Manager).
Aussage: Das System soll den Betrieb mehrerer Filialen innerhalb einer Firma (gemeinsame Datenbank, filialabhängige Nummern/Rechte/Auswertungen) sowie mehrerer Firmen (getrennte Datenbanken mit je eigenem Dienst) unterstützen.
Ergebnis: Filialbenutzer arbeiten nur in ihrem Filialkontext; getrennte Firmen teilen keine Daten.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Administration\Mandatory\MandatoryBL.cs Z.55–112 – Begründung: Nummernkreisauflösung Filiale>Mandant.
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\ReceiptBL.cs Z.10251–10295 – Begründung: Filial-Isolation bei Belegen.
- [PRIMÄR] src\webservice\c-entron.misc.ConnectionManager\Dialogs\AdditionalServiceViewModel.cs Z.22–97 – Begründung: Sub-Web-Services je Datenbank.
Prüfidee: Test: Benutzer mit „nur eigene Filiale" legt Beleg für fremde Filiale an → Ablehnung; zwei Filialen ziehen getrennte Rechnungsnummernkreise.
Tracelinks: SyRS-009, SyRS-014, SyRS-060
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Compliance: Unveränderlichkeit, Nachvollziehbarkeit, DSGVO
Ebene: StRS
Typ: nicht-funktional (Compliance)
Akteur: Buchhaltung, Datenschutzbeauftragter, Prüfer
Vorbedingung: –
Fakt: Rechnungen sind festschreibbar (IsFixed) und nach FiBu-Export storno-gesperrt; Belege werden versioniert statt überschrieben; zahlreiche fachliche Log-/Historientabellen (61 *Log/*History-Entities: Rechte, Passwörterzugriffe, Bestände, Belege, Geräte, Produktion) dokumentieren Änderungen mit Nutzer/Zeit; ein DSGVO-Modul löscht auf Anfrage mit protokolliertem Marker („DSGVO: Auf Anfrage gelöscht …"); ein AV-/SEPA-Online-Signaturkanal existiert.
Aussage: Das System soll steuer- und datenschutzrechtliche Anforderungen unterstützen: Unveränderlichkeit festgeschriebener/exportierter Rechnungen, versionierte Änderungshistorie der Belege, auditierbare Protokolle sicherheits- und abrechnungsrelevanter Vorgänge sowie eine kontrollierte, selbst protokollierte DSGVO-Datenlöschung.
Ergebnis: Prüfrelevante Vorgänge sind rekonstruierbar; Löschpflichten sind erfüllbar, ohne die Nachweisbarkeit der Löschung selbst zu verlieren.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\Receipts\Invoices\ReceiptInvoiceBL.cs Z.86–206 – Begründung: Festschreibung + Stornosperren.
- [PRIMÄR] src\backend\Centron.BL\Administration\DataSecurity\DataSecurityBL.cs Z.26–69 – Begründung: DSGVO-Cleanup mit Marker, Recht + Lizenz.
- [PRIMÄR] src\backend\Centron.BL\Administration\Rights\AppRightsBL.cs Z.762–857; src\backend\Centron.BL\PasswordManagementArea\PasswordManagementKeywordBL.cs Z.21–36 – Begründung: Audit-Trails sicherheitsrelevanter Aktionen.
Prüfidee: Test: festgeschriebene Rechnung ändern → Ablehnung; DSGVO-Lauf entfernt inaktive Kundendaten und hinterlässt Löschmarker.
Tracelinks: SyRS-011, SyRS-017, SyRS-057
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: Integration in die Kommunikationsumgebung (E-Mail, Kalender, Outlook, Telefonie)
Ebene: StRS
Typ: Schnittstelle
Akteur: Alle Mitarbeiter
Vorbedingung: Mail-/Graph-/TAPI-Konfiguration
Fakt: Mailversand über SMTP, Exchange-EWS oder Microsoft Graph (App-only) mit objektbezogenen Vorlagen; bidirektionaler Kalenderabgleich mit Exchange/Microsoft 365 (Delta-Sync, Datenschutz privater Termine, Serienbehandlung); Outlook-Web-Add-in ordnet Mails Tickets/Kunden/Belegen zu; Telefonie über TAPI und Teams-Anrufprotokolle mit Anruferauflösung; Terminanfragen an Kunden mit Annahme-/Ablehnungslink; Echtzeit-Benachrichtigungen (SignalR) inkl. @-Erwähnungen.
Aussage: Das System soll in die vorhandene Microsoft-Kommunikationsumgebung integriert sein, sodass E-Mails, Termine und Anrufe ohne Medienbruch mit ERP-Vorgängen verknüpft werden.
Ergebnis: Kommunikationsereignisse sind Vorgängen zugeordnet; Termine sind in beiden Welten konsistent, private Termininhalte bleiben geschützt.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Mail\Factory\CentronMailFactory.cs Z.29–53 – Begründung: drei Transportwege.
- [PRIMÄR] src\backend\Centron.BL\Sales\Calendar\ScheduleBL.cs Z.1052–1700 – Begründung: Delta-Sync inkl. Privatsphäre-Regeln.
- [PRIMÄR] src\webservice\Centron.Host\RealTimeServices\TapiClientHub.cs Z.9–66; src\backend\Centron.BL\Tapi\PhoneCallBL.cs Z.283–352 – Begründung: Telefonie-Kanäle.
- [SEKUNDÄR] src\nexus\CentronNexus.OutlookAddIn\Manifest\Manifest.xml – Begründung: Outlook-Add-in-Funktionsumfang.
Prüfidee: Test: privater Outlook-Termin erscheint im ERP nur als „Privater Termin"; Ticket-Termin-Zeitänderung in Outlook wird nicht ins ERP übernommen (Nexus source of truth).
Tracelinks: SyRS-044, SyRS-045, SyRS-046, SyRS-052, SyRS-067, SyRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Führungsinformationen und Leistungscontrolling
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung, Teamleitung, Controlling
Vorbedingung: Rechte (MANAGEMENT_INFO bzw. RIGHT_MITARBEITERAUSLASTUNG)
Fakt: „Management Info" liefert Kennzahlen (Auftrags-/Angebotsbestand, Deckungsbeitrag, Lieferrückstand, Lagerwert, offene Posten, Umsatz/Gewinn im Zeitverlauf) filial-/produktgruppenfiltert; „Leistungsnachweise" berechnet je Mitarbeiter/Tag fakturierbare, fakturierte und nicht fakturierbare Stunden inkl. Feiertags-/Abwesenheitslogik; Fremd-Auslastung wird ohne Sonderrecht maskiert.
Aussage: Das System soll Geschäftsleitungs-Kennzahlen und die Fakturierbarkeitsquote der Mitarbeiter auswertbar machen, mit rechtegesteuerter Sicht (nur eigene Filiale, nur eigene Auslastung).
Ergebnis: Steuerungsrelevante Kennzahlen sind ohne Export in Drittwerkzeuge verfügbar.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Statistics\Sales\ManagementInfo\ManagementInfoBL.cs Z.24–445 – Begründung: Kennzahlenumfang.
- [PRIMÄR] src\backend\Centron.BL\Statistics\Administration\Employees\EmployeeUtilizationBL.cs Z.32–278 – Begründung: Auslastungsrechnung + Maskierung.
Prüfidee: Vergleichsrechnung einer Beispielwoche gegen manuell ermittelte Stundenwerte.
Tracelinks: SyRS-062, SyRS-061
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-019
Titel: Kundenspezifische Anpassbarkeit ohne Programmierung
Ebene: StRS
Typ: nicht-funktional (Anpassbarkeit)
Akteur: Key-User/Administrator des Kunden
Vorbedingung: Administrationsrechte
Fakt: Frei definierbare Zusatzfelder je Objektart (ModuleCustomProperty inkl. Pflichtfeld/Maske/Suche), freie Tabellen (CustomTables), in der Datenbank gespeicherte und anpassbare Reports (FastReport, Import/Export), ~1.200 Systemeinstellungen (zwei Settings-Kataloge), Mail-/Textvorlagen, vorlagenbasierte Massenänderung von Belegpositionen (MassUpdate, asynchron).
Aussage: Das System soll durch Kunden ohne Codeänderung anpassbar sein: eigene Felder, eigene Auswertungen/Belegdrucke, umfangreiche Parametrisierung und Massenpflege.
Ergebnis: Kundenindividuelle Anforderungen sind konfigurativ lösbar; Reports sind ohne Release austauschbar.
Belege:
- [PRIMÄR] src\backend\Centron.Entities\Entities\Administration\Customization\ModuleCustomProperty.cs Z.9–19 – Begründung: Custom-Felder inkl. IsMandatory.
- [PRIMÄR] src\backend\Centron.Entities\Entities\ReportEngine\Base\ReportDataBase.cs Z.8–22 – Begründung: Reports als DB-Inhalt.
- [PRIMÄR] src\backend\Centron.BL\MassUpdate\MassUpdateBL.cs Z.60–160 – Begründung: Massenpflege über 6 Belegarten.
Prüfidee: Test: Pflicht-Zusatzfeld an Kunde definieren → Anlage ohne Wert wird abgewiesen; Reportänderung wirkt ohne Neuinstallation.
Tracelinks: SyRS-063, SyRS-061
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Betriebs- und Bereitstellungsmodelle (On-Premises, Linux/Container, Web)
Ebene: StRS
Typ: nicht-funktional (Übertragbarkeit/Betrieb)
Akteur: Betreiber
Vorbedingung: –
Fakt: Der Web-Service läuft als Windows-Dienst (HTTP.sys) und unter Linux/Docker (Kestrel, Alpine-Container, TLS per PFX); Nexus als Windows-Dienst (MSI) und Container; der WPF-Client benötigt Windows; DB-Schema-Migration erfolgt automatisch beim Dienststart; Hintergrunddienste sind einzeln per DB-Flag deaktivierbar und überwacht; Builds sind signiert (Azure Trusted Signing) und versionsrückverfolgbar (Nerdbank GitVersioning).
Aussage: Das System soll wahlweise On-Premises unter Windows oder containerisiert unter Linux betreibbar sein, sich beim Update selbst migrieren und betreibbar/überwachbar sein (steuerbare Hintergrunddienste, signierte Artefakte, eindeutige Versionszuordnung).
Ergebnis: Ein Update besteht aus Dienst-Austausch; die Datenbank wird automatisch, transaktional und idempotent aktualisiert.
Belege:
- [PRIMÄR] src\webservice\Centron.Host\CentronHost.cs Z.100–151, 366–417 – Begründung: OS-abhängiges Hosting + Migrations-Start.
- [PRIMÄR] src\webservice\Centron.Host\AspNetCore\HostedServices\ManagedBackgroundService.cs Z.23–157 – Begründung: steuer-/überwachbare Dienste.
- [SEKUNDÄR] docker\c-entron-webservice\Dockerfile; .github\workflows\build.yml Z.184–334 – Begründung: Container-Weg + Signaturpflicht.
Prüfidee: Betriebstest: Dienststart gegen ältere DB führt Skripte aus und startet erst bei Erfolg; Dienst-Deaktivierung per DB-Flag stoppt Ausführung binnen 60 s.
Tracelinks: SyRS-001, SyRS-049, SyRS-050, SyRS-053, SyRS-054, SyRS-060
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-021
Titel: Deutschsprachiger Zielmarkt mit englischer Zweitsprache
Ebene: StRS
Typ: nicht-funktional (Lokalisierung)
Akteur: Alle Benutzer
Vorbedingung: –
Fakt: Deutsch ist Basissprache (Resource-Fallback, deutsche Fehlermeldungen in BL), Englisch die einzige Zusatzsprache (resx `.en`, Nexus de-DE/en-US); die Entwicklungsrichtlinie schreibt German-First vor; steuerliche Logik (DATEV, XRechnung, §13b-Texte, CH-Rundung, AT-ebInterface) adressiert DACH.
Aussage: Das System soll primär den deutschsprachigen Markt (DE/AT/CH inkl. länderspezifischer Steuer-/Rundungsregeln) bedienen; alle Benutzertexte liegen deutsch vor, englisch als Zweitsprache.
Ergebnis: Deutsche Benutzerführung vollständig; englische weitgehend (WPF ca. 90 % übersetzt).
Belege:
- [KONTEXT] docs\getting-started\general-structure.md Z.114–141 (German-First-Policy) – Begründung: dokumentierte Vorgabe.
- [SEKUNDÄR] src\centron\Centron.WPF.UI\Resources\LocalizedStrings.resx / .en.resx (2812/2522 Einträge) – Begründung: Ist-Stand Übersetzungsumfang.
- [PRIMÄR] src\nexus\CentronNexus\Shared\Services\CultureService.cs Z.15–29 – Begründung: unterstützte Kulturen de-DE/en-US.
Prüfidee: UI-Durchsicht in EN: keine leeren Texte; Fallback auf Deutsch dokumentieren.
Tracelinks: SyRS-058
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: KI-Assistenz mit kundenseitiger Anbieterwahl
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter; Betreiber (Konfiguration)
Vorbedingung: KI-Anbieter/Key konfiguriert
Fakt: Sieben produktive KI-Aktionen (Ticket-Titel/-Beschreibung/-Kommentar, Zeiterfassungstext, E-Mail-Text, Übersetzung, Kategorisierung) plus Chat/Tool-Calling; Anbieter je Installation wählbar (OpenAI, IONOS, OpenAI-kompatibel, Tensorx, ClaudeCode, Mistral, Google); Prompts deutsch mit Anti-Halluzinations-Regeln; Nutzung wird telemetriert.
Aussage: Das System soll KI-gestützte Textassistenz im Service-Alltag bereitstellen, wobei der Kunde den KI-Anbieter (inkl. EU-/Self-Hosted-Optionen) selbst bestimmt.
Ergebnis: Textqualität und Erfassungsgeschwindigkeit werden unterstützt, ohne Anbieter-Lock-in.
Belege:
- [PRIMÄR] src\backend\Centron.BL\ArtificialIntelligence\ApiClientFactory.cs Z.11–55 – Begründung: Multi-Provider.
- [PRIMÄR] src\backend\Centron.BL\ArtificialIntelligence\Prompts\AiActionId.cs Z.8–22 – Begründung: Funktionsumfang.
Prüfidee: Test: Anbieterwechsel per Einstellung ohne Codeänderung; Aktion „Ticket-Beschreibung verbessern" liefert Text.
Tracelinks: SyRS-059
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: Projekt- und Einsatzplanung
Ebene: StRS
Typ: funktional
Akteur: Projektleiter, Dispatcher
Vorbedingung: –
Fakt: CRM-Projekte bündeln Vertrieb (Plan-/Angebots-/Auftragsvolumen mit Erreichungsgraden), Tickets (Fortschritt aus Zeiten, Gantt mit Fälligkeits-Meilensteinen) und Ablage; Ticket-Projekte bieten Aufgabenbäume mit Verantwortlichen, Netzplan-Abhängigkeiten (4 Typen) und personalisierte Änderungs-Sammelmails; der Einsatzplan überlagert Projekte, Tickets, Zeiten und Termine rechtegefiltert.
Aussage: Das System soll Projekte vertrieblich und operativ planbar machen (Budgetverfolgung, Aufgabenstruktur, Terminabhängigkeiten, Einsatzübersicht) und Beteiligte automatisch über Änderungen informieren.
Ergebnis: Projektfortschritt und Ressourcennutzung sind aus operativen Daten (Tickets/Zeiten) abgeleitet statt separat gepflegt.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Sales\Customers\CrmProjects\CrmProjectBL.cs Z.105–863 – Begründung: CRM-Projekt inkl. Fortschritt/Gantt.
- [PRIMÄR] src\backend\Centron.BL\WebServices\TicketProjects\TicketProjectWebserviceBL.cs Z.331–660 – Begründung: Aufgaben-Änderungslog + Sammelmail.
- [PRIMÄR] src\backend\Centron.BL\Sales\Support\HelpdeskSchedulerBL.cs Z.35–212 – Begründung: Einsatzplan-Aggregation.
Prüfidee: Test: Terminänderung an Aufgabe → Log-Eintrag; Sammelmail an Verantwortliche mit markierten Änderungen.
Tracelinks: SyRS-065
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Auftragsbezogene Produktion mit Werkerführung
Ebene: StRS
Typ: funktional
Akteur: Fertigungsplaner, Werker
Vorbedingung: Lizenz ProductionManagement; Auftragsposition mit Produktionsartikel
Fakt: Fertigungsaufträge entstehen ausschließlich aus Auftragspositionen mit Produktionsartikel; sie bestehen aus Arbeitsschritten (Dauer, Arbeitsplatztyp, Maße), die Werker im Web übernehmen (Doppelbelegungsschutz) und fertigmelden; 26 Log-Ereignistypen protokollieren feldgenau.
Aussage: Das System soll kundenauftragsbezogene Fertigung (make-to-order) mit schrittweiser Werkerführung, Arbeitsplatz-/Maschinenzuordnung und lückenloser Änderungshistorie unterstützen.
Ergebnis: Fertigungsfortschritt je Auftragsposition ist in Echtzeit sichtbar; kein Arbeitsschritt wird doppelt bearbeitet.
Belege:
- [PRIMÄR] src\centron\Centron.WPF.UI\Modules\Production\ProductionOrder\AddProductionOrder\AddProductionOrderViewModel.cs Z.111–137 – Begründung: Anlage nur aus Produktionsartikel-Position.
- [PRIMÄR] src\nexus\CentronNexus\ProductionOrderManagement\Components\WorkStepTemplateComponent.razor Z.134–188 – Begründung: Übernahme-/Fertigmeldelogik.
- [PRIMÄR] src\backend\Centron.Interfaces\Production\ProductionOrderLogKind.cs Z.9–76 – Begründung: Protokollpflicht.
Prüfidee: Test: zwei Werker übernehmen denselben Schritt → zweiter erhält Hinweis; Fertigmeldung setzt ProducedAmount.
Tracelinks: SyRS-064
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Nutzungsdatenübermittlung an den Hersteller (Transparenz-/Steuerungsanforderung)
Ebene: StRS
Typ: nicht-funktional (Datenschutz/Vertrag)
Akteur: Hersteller; Betreiber; betroffene Mitarbeiter
Vorbedingung: Lizenz geladen
Fakt: Jede Installation aggregiert API-/KI-/Modulnutzung in 15-Minuten-Buckets je Benutzer, Gerät (Hardware-Fingerprint) und Lizenzart und lädt sie komprimiert an den Hersteller-Dienst „c-entron Office" hoch (inkl. DatabaseGuid, DatabaseName, CustomerNumber); zusätzlich meldet ein Analytics-Kanal Modulnutzungsdauern je Mitarbeiter; ein Endnutzer-Opt-out ist im Code nicht erkennbar.
Aussage: Das System soll Produktnutzungsdaten an den Hersteller übermitteln. [HYPOTHESE] Zweck ist Lizenz-/Produktsteuerung; für ein Zielsystem ist die datenschutzrechtliche Grundlage (AVV, Betriebsvereinbarung, Opt-out) als Stakeholder-Anforderung explizit zu klären, da personenbeziehbare Verhaltensdaten übermittelt werden.
Ergebnis: Nutzungsdaten liegen dem Hersteller pro Kunde/Benutzer/Gerät vor.
Belege:
- [PRIMÄR] src\webservice\Centron.Host\AspNetCore\Telemetry\HttpTelemetryUploadClient.cs Z.33–141 – Begründung: Upload-Inhalt und Empfänger.
- [PRIMÄR] src\backend\Centron.BL\Telemetry\TelemetryBL.cs Z.36–194 – Begründung: erfasste Dimensionen inkl. UserID.
- [PRIMÄR] src\centron\Centron.WPF.UI\Managers\CentronAnalyticsManager.cs Z.54–127 – Begründung: Modulnutzungsdauer je Mitarbeiter.
Prüfidee: Netzwerkmitschnitt einer Installation: Upload-Frequenz (15 min) und Payload-Felder verifizieren; Prüfung auf Abschaltbarkeit.
Tracelinks: SyRS-056
Konsolidierung: nein
Status: HYPOTHESE (Zweck/Rechtsgrundlage; die Übermittlung selbst ist belegt)
```
```
ID: StRS-026
Titel: Verwaltung von Kundenzugangsdaten (Passwortmanager) mit Zugriffsnachweis
Ebene: StRS
Typ: Sicherheit
Akteur: Servicemitarbeiter (Hotline), Kunde (Datengeber)
Vorbedingung: Lizenz PasswordManager
Fakt: Ein Passwortmanager-Modul speichert Fremdzugangsdaten der Kunden verschlüsselt (AES mit installationsspezifischem Masterkey), steuert Sichtbarkeit/Bearbeitung feingranular je (Kunde, Mitarbeiter) über Richtlinien-Flags inkl. Versiegelung/Siegelbruch und optionaler TOTP-PIN-Abfrage vor Anzeige, und protokolliert jede Entschlüsselung (PasswordManagementAccessLog).
Aussage: Das System soll Zugangsdaten der betreuten Kunden verschlüsselt verwalten, den Zugriff je Kunde und Mitarbeiter steuern (inkl. Vier-Augen-/Versiegelungskonzept und Zweitfaktor vor Einsichtnahme) und jede Einsichtnahme revisionssicher nachweisen.
Ergebnis: Kundenpasswörter sind nie im Klartext gespeichert; jeder Zugriff ist einem Mitarbeiter und Zeitpunkt zuordenbar.
Belege:
- [PRIMÄR] src\backend\Centron.BL\PasswordManager\PasswordManagerBL.cs Z.92–188, 525–528, 700, 1051–1052 – Begründung: Verschlüsselung, Richtlinien-Flags, Feld-Nullung bei API-Abruf.
- [PRIMÄR] src\backend\Centron.BL\PasswordManagementArea\PasswordManagementKeywordBL.cs Z.21–36 – Begründung: Zugriffsprotokoll bei Entschlüsselung.
- [PRIMÄR] src\backend\Centron.BL\TwoFactorAuthenticator\TwoFactorAuthenticationBL.cs Z.43–54 – Begründung: TOTP-PIN vor Anzeige.
Prüfidee: Test: Anzeige eines versiegelten Zugangsdatums erfordert Siegelbruch + erzeugt Logeintrag; DB-Inspektion zeigt nur Chiffretext.
Tracelinks: SyRS-070
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-027
Titel: Zentrale Stammdatenverwaltung (Geschäftspartner, Artikel, Mitarbeiter)
Ebene: StRS
Typ: funktional (Daten)
Akteur: Stammdatenpfleger, Vertrieb, Einkauf
Vorbedingung: –
Fakt: Geschäftspartner werden als Account mit Rollen (Kunde/Lieferant/Kontakt/Kundenarten) und Hierarchie Anschrift→Ansprechpartner geführt (genau eine Standardanschrift/-kontakt erzwungen; Löschschutz bei offenen Vorgängen); der Artikelstamm trägt flagbasierte Artikelarten, vier Preislisten, Staffeln, Stücklisten, GS1-EAN-Prüfziffernvalidierung und Eindeutigkeitsregeln; Mitarbeiter sind über „Mitarbeiterartikel" mit der Leistungsabrechnung verknüpft; Nummernkreise decken auch Stammdaten ab; bei Anlage entstehen automatisch DMS-Ordnerstrukturen.
Aussage: Das System soll Geschäftspartner-, Artikel- und Mitarbeiterstammdaten zentral, validiert und rollenfähig verwalten; Stammdaten sind führend für Preisfindung, Steuerlogik, Abrechnung und Dokumentablage.
Ergebnis: Alle Bewegungsprozesse greifen auf konsistente, validierte Stammdaten zu; Deaktivierung (z. B. Mitarbeiteraustritt) zerstört keine historische Abrechenbarkeit.
Belege:
- [PRIMÄR] src\backend\Centron.BL\Accounts\AccountBL.cs Z.490–803 (Rollenrechte, Löschschutz) – Begründung: Kernvalidierungen Geschäftspartner.
- [PRIMÄR] src\backend\Centron.BL\Warehousing\ArticleBL.cs Z.1330–1567 (ValidateArticleBeforeSave inkl. EAN-Prüfziffer) – Begründung: Artikelvalidierung.
- [PRIMÄR] src\backend\Centron.BL\EmployeeArea\EmployeeArticleBL.cs Z.23–61 (EOL statt Löschen) – Begründung: Abrechenbarkeit bleibt erhalten (Commit 644e5cc068).
Prüfidee: Test: Artikel mit falscher EAN-Prüfziffer → Ablehnung; Kunde mit offener Rechnung löschen → Ablehnung; deaktivierter Mitarbeiter: alte Zeiten bleiben abrechenbar.
Tracelinks: SyRS-069
Konsolidierung: nein
Status: belegt
```
---
## 3. Abgrenzung / bewusste Nicht-Ziele (aus Code ableitbar)
- **Keine eigene Finanzbuchhaltung:** Es gibt Export/Import zu Fremd-FiBu (DATEV u. a.), aber keine Hauptbuchführung. Beleg: `BookKeepingExportBL` (nur Export/OPOS-Import) [PRIMÄR].
- **Keine Mahnzinsen/-gebührenberechnung:** Im Mahnwesen ist keine Zins-/Gebührenlogik implementiert; DATEV-Mahnfelder werden leer exportiert. Beleg: `DunningBL`/`DatevAscii` Felder 232–254 leer [PRIMÄR, Abwesenheitsbefund].
- **Keine Chargenverwaltung:** Rückverfolgung nur über Einzel-Seriennummern. Beleg: `BarcodeState.cs`, keine Chargen-Entität [PRIMÄR, Abwesenheitsbefund].
- **Barbelege im .NET-Stack blockiert:** trotz vorhandener Datenstrukturen („Aktuell werden leider noch keine Bar-Belege unterstützt."). Beleg: `ReceiptBL.cs` Z.3763–3765 [PRIMÄR]; Status: belegt; Workaround (Delphi-Altfunktion nicht migriert).
@@ -0,0 +1,86 @@
# Traceability-Matrix (StRS ↔ SyRS ↔ SwRS)
Forward-Traceability: StRS → SyRS → SwRS (eine Zeile je SyRS-Anforderung, gruppiert nach StRS).
Backward-Traceability ist in den Dokumenten selbst enthalten (Feld `Tracelinks` jeder SyRS-/SwRS-Anforderung).
Der `Artefaktbeleg` nennt je Zeile einen repräsentativen PRIMÄR-Beleg; vollständige Beleglisten stehen in den Einzelanforderungen.
`–` = keine eigene SwRS-Verfeinerung (Systemanforderung direkt belegt).
| StRS-ID | SyRS-ID | SwRS-ID(s) | Artefaktbeleg (repräsentativ) |
|---|---|---|---|
| StRS-001 | SyRS-001 | SwRS-001 | src\webservice\Centron.Host\CentronHost.cs Z.274–282 |
| StRS-001, StRS-003 | SyRS-013 | SwRS-016, SwRS-017, SwRS-018, SwRS-019, SwRS-020, SwRS-021, SwRS-022 | Centron.BL\Sales\Receipts\ReceiptBL.cs Z.3535–3950 |
| StRS-001, StRS-005 | SyRS-020 | SwRS-031, SwRS-034, SwRS-038, SwRS-039, SwRS-069 | Centron.BL\Sales\Support\HelpdeskBL.cs Z.418–466 |
| StRS-001, StRS-007 | SyRS-025 | SwRS-024, SwRS-026, SwRS-027 | AutomaticFacturaBL.Contracts.cs Z.1885–2019 |
| StRS-001, StRS-010 | SyRS-035 | SwRS-051 | Centron.BL\CustomerArea\RmaBL.cs Z.352–1996 |
| StRS-001, StRS-011 | SyRS-039 | SwRS-053, SwRS-054 | BookKeepingExportDatevAscii.cs Z.551–844 |
| StRS-002, StRS-013 | SyRS-006 | SwRS-006, SwRS-007 | Auth\AuthenticatorFactory.cs Z.54–140 |
| StRS-002, StRS-013, StRS-015 | SyRS-009 | SwRS-011, SwRS-032 | AppRightsBL.cs Z.644–664 |
| StRS-002, StRS-012, StRS-013 | SyRS-010 | SwRS-012 | WebRightsVisibility.cs Z.10–59 |
| StRS-002, StRS-012 | SyRS-028 | SwRS-012, SwRS-015, SwRS-043 | HelpdeskSearchBL.cs Z.536–565 |
| StRS-003 | SyRS-014 | SwRS-023 | NumberGroupBL.cs Z.62–134 |
| StRS-003, StRS-007 | SyRS-015 | SwRS-024, SwRS-025, SwRS-026, SwRS-030 | ReceiptItemPriceBL.cs Z.154–286 |
| StRS-003, StRS-011, StRS-016 | SyRS-017 | SwRS-020 | ReceiptInvoiceBL.cs Z.86–206 |
| StRS-003 | SyRS-018 | SwRS-028 | DownPaymentBL.cs Z.82–343 |
| StRS-003, StRS-008 | SyRS-038 | SwRS-017 | Centron.Api.Gls\CentronGlsLogic.cs Z.15–58 |
| StRS-004 | SyRS-027 | SwRS-040, SwRS-041 | SharedDocumentBL.cs Z.496–678 |
| StRS-005 | SyRS-021 | SwRS-033 | Escalation\EscalationBL.cs Z.313–426 |
| StRS-005, StRS-013 | SyRS-022 | SwRS-031, SwRS-032 | HelpdeskBL.cs Z.233–291 |
| StRS-005 | SyRS-051 | SwRS-068 | IndexSearchBL.cs Z.49–73 |
| StRS-005, StRS-007 | SyRS-068 | SwRS-066 | ExpectedEventsBL.cs Z.22–213 |
| StRS-006, StRS-013 | SyRS-023 | SwRS-035, SwRS-036, SwRS-073 | HelpdeskTimerWebServiceBL.cs Z.327–381 |
| StRS-006 | SyRS-024 | SwRS-036, SwRS-037 | ReceiptItemTimerBL.cs Z.390–497 |
| StRS-006 | SyRS-066 | – | MyDayNotificationsBL.cs Z.115–231 |
| StRS-007 | SyRS-047 | SwRS-052 | RiverDivoBL.cs Z.86–441 |
| StRS-007 | SyRS-048 | SwRS-052 | DocuFormRestApiClient.cs Z.48–110 |
| StRS-008 | SyRS-029 | SwRS-017, SwRS-019, SwRS-046 | SupplierDeliveryListSpecificLogic.cs Z.148–374 |
| StRS-008 | SyRS-030 | SwRS-047 | OrderSuggestionListBL.cs Z.87–242 |
| StRS-008 | SyRS-036 | SwRS-052 | SupplierEdiBL.cs Z.1364–1414 |
| StRS-008 | SyRS-037 | SwRS-052 | ITscopeExternalArticleSearchProvider.cs Z.45–225 |
| StRS-009 | SyRS-031 | SwRS-044, SwRS-045, SwRS-046 | ScriptMethod11482.cs Z.25–54 (cvw_ArticleCount) |
| StRS-009 | SyRS-032 | SwRS-048 | ReceiptBarcodeBL.cs Z.85–122 |
| StRS-009 | SyRS-033 | SwRS-049 | InventoryBL.cs Z.797–944 |
| StRS-009 | SyRS-034 | SwRS-050 | SecondStockArticleBL.cs Z.101–130 |
| StRS-011 | SyRS-016 | SwRS-026, SwRS-027 | ReceiptItemAccountBL.cs Z.115–189 |
| StRS-011 | SyRS-019 | SwRS-029 | ReceiptBL.cs Z.8636–8690, 10205–10244 |
| StRS-011 | SyRS-040 | SwRS-055 | InvoiceZugferdBL.cs Z.124–217 |
| StRS-011 | SyRS-041 | SwRS-056 | SepaFileGeneratorV2.cs Z.99–289 |
| StRS-011 | SyRS-042 | SwRS-057 | OnlineBankingAccountTransactionsBL.cs Z.581–1086 |
| StRS-011 | SyRS-043 | SwRS-058 | DunningRunBL.cs Z.200–315 |
| StRS-012 | SyRS-026 | SwRS-042 | ReceiptCartReleaseSystemBL.cs Z.65–283 |
| StRS-013, StRS-014 | SyRS-007 | SwRS-008, SwRS-009 | TicketBL.cs Z.26–170; AccessTokenBL.cs Z.457–488 |
| StRS-013 | SyRS-008 | SwRS-010 | TwoFactorAuthBL.cs Z.82–135 |
| StRS-013, StRS-016 | SyRS-011 | SwRS-011 | AppRightsBL.cs Z.762–857 |
| StRS-013 | SyRS-055 | SwRS-006, SwRS-007, SwRS-010, SwRS-014 | SHA1Decoder.cs Z.9–17; AESCryptoLogic.cs Z.77–92 |
| StRS-014 | SyRS-012 | SwRS-013, SwRS-075 | LicenseManager.cs Z.219–302 |
| StRS-015, StRS-020 | SyRS-060 | SwRS-066 | .github\workflows\build.yml Z.313–334; CentronHost.cs Z.114–151 |
| StRS-016 | SyRS-057 | SwRS-064 | DataSecurityBL.cs Z.26–69 |
| StRS-017 | SyRS-004 | SwRS-003 | CentronSignalR.cs Z.9–15 |
| StRS-017 | SyRS-044 | SwRS-059 | CentronMailFactory.cs Z.29–53 |
| StRS-017 | SyRS-045 | SwRS-060 | ScheduleBL.cs SyncByGraphV2 Z.1052–1204 |
| StRS-017 | SyRS-046 | SwRS-003 | TapiClientHub.cs Z.9–66 |
| StRS-017 | SyRS-052 | SwRS-003 | NexusNotificationsBL.cs Z.35–405 |
| StRS-017 | SyRS-067 | SwRS-060 | AppointmentRequestBL.cs Z.29–114 |
| StRS-018 | SyRS-062 | SwRS-011 | ManagementInfoBL.cs Z.24–445 |
| StRS-018, StRS-019 | SyRS-061 | SwRS-064 | ReportDataBase.cs Z.8–22; PdfStrategies.cs Z.23–147 |
| StRS-019 | SyRS-063 | – | ModuleCustomPropertyBL.cs Z.20–83; MassUpdateBL.cs Z.60–160 |
| StRS-020 | SyRS-002 | SwRS-002, SwRS-003, SwRS-004 | CentronWcfBridge.cs Z.35–81 |
| StRS-020 | SyRS-003 | SwRS-005 | RegisterCentronApiVersioning.cs Z.9–23 |
| StRS-020 | SyRS-005 | SwRS-004 | TryCatchInterceptor.cs Z.19–41 |
| StRS-020 | SyRS-049 | SwRS-066 | ManagedBackgroundService.cs Z.23–157 |
| StRS-020 | SyRS-050 | SwRS-021, SwRS-061, SwRS-062, SwRS-063, SwRS-064 | ScriptEngineBL.cs Z.40–177 |
| StRS-020 | SyRS-053 | SwRS-004, SwRS-065 | WebServiceConfigDAOConnection.cs Z.8–19 |
| StRS-020 | SyRS-054 | SwRS-065, SwRS-066 | DAOFactory.cs Z.212–273 |
| StRS-021 | SyRS-058 | SwRS-001 | CultureService.cs Z.15–29; LocalizedStrings*.resx |
| StRS-022 | SyRS-059 | SwRS-067 | ApiClientFactory.cs Z.11–55 |
| StRS-023 | SyRS-065 | SwRS-069 | TicketProjectWebserviceBL.cs Z.331–425 |
| StRS-024 | SyRS-064 | SwRS-070 | WorkStepTemplateComponent.razor Z.134–188 |
| StRS-025 | SyRS-056 | SwRS-067 | HttpTelemetryUploadClient.cs Z.57–74 |
| StRS-026 | SyRS-070 | SwRS-074, SwRS-014 | PasswordManagerBL.cs Z.92–188 |
| StRS-027 | SyRS-069 | SwRS-071, SwRS-072, SwRS-073 | AccountRepository.cs Z.904–1005; ArticleBL.cs Z.1330–1567 |
## Abdeckungsübersicht
- **StRS-Abdeckung:** Alle 27 StRS-Anforderungen sind durch mindestens eine SyRS-Anforderung verfeinert.
- **SyRS-Abdeckung:** Alle 70 SyRS-Anforderungen referenzieren mindestens eine StRS-Anforderung (Backward). 68 von 70 besitzen SwRS-Verfeinerungen; SyRS-063 und SyRS-066 sind bewusst ohne eigene SwRS-Ebene (Systemanforderung direkt implementierungsbelegt, siehe Vermerk in den Anforderungen).
- **SwRS-Abdeckung:** Alle 75 SwRS-Anforderungen referenzieren mindestens eine existierende SyRS-Anforderung.
- **Mehrfachzuordnungen** (eine SwRS unter mehreren SyRS) sind beabsichtigt (Querschnittskomponenten, z. B. SwRS-003 Interceptor-Kette, SwRS-052 Integrationskatalog, SwRS-066 Dienstbasisklasse).
@@ -0,0 +1,199 @@
# Messprotokoll – V1b-Fable (builtin, `claude-fable-5`, Effort `high`) – Iteration 01, Lauf 24 (Lauf R)
> ## ⚠ Bedingungsverletzung: Die Subagenten liefen auf einem anderen Modell
>
> `--model claude-fable-5` steuerte nur den **Hauptagenten**. Die 13 Subagenten liefen auf
> **`claude-opus-5[1m]`** – dem in `~/.claude/settings.json` hinterlegten Standardmodell
> (`"model": "opus[1m]"`). Auf sie entfallen **136.694.206 von 150.340.866 Tokens (91 %)**.
>
> **Der Lauf ist damit keine Fable-Messung**, sondern ein Mischbetrieb: Fable als Hauptagent,
> Opus mit 1-Mio.-Kontext als Analysemodell. Für den Modellvergleich der Reihe ist er **nicht
> verwendbar**. Als Beleg für das Verhalten von Claude Code ist er dagegen wertvoll – siehe
> Anmerkung 1.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T22:07:48+02:00
- **Endzeit:** 2026-08-25T23:10:36+02:00
- **Dauer gesamt:** 01:02:48 (Wanduhr) bzw. 00:51:56 (`duration_ms`) — API: 03:11:37
- **Parallelbetrieb:** **nein** – der Lauf lief allein auf der Maschine. Die Zeitangaben sind
damit erstmals seit Lauf 6 wieder für Laufzeitvergleiche brauchbar.
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.7.0-15db`
- **Ablage:** `claude-fable-5/builtin/high/`
- **Parallele Läufe:** nein
- **Skill-Version:** `3.7.0` (erster Lauf mit Effort im Verzeichnisnamen)
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `builtin` (V1b) – eingebaute Subagenten zugelassen
- **Effort:** `high` – explizit per `--effort` gesetzt; Gegenprobe im Transkript: 104
Nachrichten, durchgängig `high`
- **Modell (angefordert):** `claude-fable-5`
- **Modelle (tatsächlich eingesetzt):**
- `claude-fable-5` – Hauptagent, 13.642.444 Tokens (9 %)
- **`claude-opus-5[1m]`** – Subagenten, 136.694.206 Tokens (91 %) — **nicht angefordert**
- `claude-haiku-4-5-20251001` – interne Hilfsaufrufe, 4.216 Tokens
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 33 Einträgen
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine
- **Subagenten:** **13** (alle `Explore`); 0 fehlgeschlagen
- **Verschachtelung:** `spawned` = 13, `spawned_by_subagents` = 0, `max_depth` = 1
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 46 |
| Output-Tokens | 275.863 (davon 22.340 Thinking-Tokens) |
| Cache-Write-Tokens | 627.458 |
| Cache-Read-Tokens | 11.734.030 |
| Agent-Turns | 28 |
### Gesamtlauf inkl. aller Subagenten (`modelUsage`)
| Messgröße | `claude-fable-5` | `claude-opus-5[1m]` | `claude-haiku-4-5` | Summe |
|---|---:|---:|---:|---:|
| Input-Tokens | 76 | 1.784 | 4.196 | 6.056 |
| Output-Tokens | 298.603 | 619.711 | 20 | 918.334 |
| Cache-Write-Tokens | 713.252 | 2.938.430 | 0 | 3.651.682 |
| Cache-Read-Tokens | 12.630.513 | 133.134.281 | 0 | 145.764.794 |
| Tokens gesamt | 13.642.444 | **136.694.206** | 4.216 | **150.340.866** |
**Tokens gesamt: 150.340.866** — mit Abstand der höchste Wert der gesamten Reihe. Der bisherige
Höchstwert lag bei 65.101.243 (Lauf J, V1b Sonnet); dieser Lauf übertrifft ihn um Faktor 2,3.
Ursache ist ausschließlich das Fremdmodell in den Subagenten.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `9bfd8e6e-018e-4179-a426-75d86a14912e`
- **Permission-Denials:** **0**
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = 13 (Modus `builtin`, erwartungskonform)
- **Kontrolle Modell:** **fehlgeschlagen** – `modelUsage` enthält ein nicht angefordertes Modell
- **Subagenten-Prompts:** `_meta\subagenten.md`, 13 von 13 Aufrufen erfasst (keine Verschachtelung)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 52.997 B | 27 Anforderungen |
| `SyRS.md` | 111.376 B | 70 Anforderungen |
| `SwRS.md` | 89.020 B | 75 Anforderungen |
| `Traceability.md` | 7.215 B | konsolidierte Tabelle |
| `Hypothesen.md` | 10.288 B | Sammlung der `[HYPOTHESE]`-Aussagen |
| `Glossar.md` | 16.477 B | Domänenbegriffe |
| `Analysebericht.md` | 12.269 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **172 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 27 | 15,7 % |
| SyRS | 70 | 40,7 % |
| SwRS | 75 | 43,6 % |
| **Gesamt** | **172** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 79 | 45,9 % |
| Sicherheit | 23 | 13,4 % |
| Schnittstelle | 19 | 11,0 % |
| Daten | 9 | 5,2 % |
| funktional (Daten) | 4 | 2,3 % |
| funktional (Komponente) | 4 | 2,3 % |
| nicht-funktional (Produktsteuerung) | 2 | 1,2 % |
| funktional / Sicherheit | 2 | 1,2 % |
| Schnittstelle (Zahlungsverkehr) | 2 | 1,2 % |
| funktional (Geschäftsziel) | 1 | 0,6 % |
| (27 weitere) | 27 | 15,7 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 331 |
| davon `PRIMÄR` | 314 (94,9 %) |
| davon `SEKUNDÄR` | 5 (1,5 %) |
| davon `KONTEXT` | 12 (3,6 %) |
| Belege je Anforderung (Median) | 2,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 172 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 169 | 98,3 % |
| als `HYPOTHESE` gekennzeichnet | 3 | 1,7 % |
| als Workaround vermerkt | 15 | 8,7 % |
| Konsolidierungskandidaten | 17 | 9,9 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (58 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 172 von 172 mit Tracelinks (100,0 %) |
## Anmerkungen/Auffälligkeiten
1. **`--model` steuert nur den Hauptagenten, nicht zwingend die Subagenten.** Das ist der
zentrale Befund dieses Laufs. Eine Gegenprüfung über alle 24 Läufe zeigt, dass der Effekt
**ausschließlich hier** auftritt:
| Kombination | Läufe | Modelle in `modelUsage` |
|---|---:|---|
| Sonnet + `builtin` | 11 | nur `claude-sonnet-5` (+ Haiku) |
| Sonnet + `solo` | 5 | nur `claude-sonnet-5` (+ Haiku) |
| Opus + `solo` | 5 | nur `claude-opus-5` (+ Haiku) |
| Fable + `solo` | 2 | nur `claude-fable-5` (+ Haiku) |
| **Fable + `builtin`** | **1** | **Fable + `claude-opus-5[1m]`** |
Sonnet und Opus werden also an die Subagenten durchgereicht, Fable nicht. Statt dessen greift
das in `~/.claude/settings.json` hinterlegte Standardmodell `opus[1m]`. Die naheliegende
Erklärung: Fable steht als Subagenten-Modell nicht zur Verfügung, und Claude Code fällt auf
die Sitzungsvorgabe zurück statt auf den `--model`-Wert. **`--safe-mode` verhindert das
nicht** – es deaktiviert Customizations, nicht die Modellwahl.
2. **Konsequenz für die Versuchsanordnung:** Bei Modus `builtin` ist das Modell **nicht allein
durch `--model` festgelegt**. Es genügt nicht, den Flag-Wert ins Protokoll zu schreiben; die
tatsächlich eingesetzten Modelle müssen nach jedem Lauf aus `modelUsage` gegengeprüft werden.
Enthält es ein nicht angefordertes Modell, ist die Bedingung verletzt und der Lauf für
Modellvergleiche unbrauchbar. Diese Prüfung wird als Pflichtschritt in den Skill aufgenommen.
3. **Alle bisherigen Läufe sind nicht betroffen.** Die Gegenprüfung ergab für die 23 Vorläufe
ausschließlich das jeweils angeforderte Modell plus Haiku. Die bisherigen Ergebnisse und
Vergleiche bleiben gültig.
4. **Der Lauf zeigt beiläufig, was Opus mit Subagenten leistet.** 172 Anforderungen (27/70/75)
bei 13 `Explore`-Subagenten und nur 28 Hauptagent-Turns. Zum Vergleich: Der Sonnet-V1b-Block
F–J erreichte 113 bis 246 Anforderungen. Der Wert liegt also im erwarteten Bereich – erkauft
mit dem 2,3-fachen Tokenverbrauch des bisherigen Maximums.
5. **Erstmals seit Lauf 6 wieder eine belastbare Zeitmessung.** Der Lauf lief allein; Wanduhrzeit
(01:02:48) und `duration_ms` (00:51:56) sind nicht parallelbetriebsverzerrt. Die API-Zeit von
03:11:37 bei 13 nebenläufigen Subagenten ergibt ein Verhältnis `api/wall` von 3,05.
6. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":11496687,"num_turns":28,"stop_reason":"end_turn","session_id":"9bfd8e6e-018e-4179-a426-75d86a14912e","total_cost_usd":142.2647820000002,"usage":{"input_tokens":46,"cache_creation_input_tokens":627458,"cache_read_input_tokens":11734030,"output_tokens":275863,"output_tokens_details":{"thinking_tokens":22340},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":627458,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1199,"cache_read_input_tokens":712846,"cache_creation_input_tokens":406,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":406},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4196,"outputTokens":20,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004296,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-fable-5":{"inputTokens":76,"outputTokens":298603,"cacheReadInputTokens":12630513,"cacheCreationInputTokens":713252,"webSearchRequests":0,"costUSD":41.826463000000004,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-fable-5","provider":"firstParty"},"claude-opus-5[1m]":{"inputTokens":1784,"outputTokens":619711,"cacheReadInputTokens":133134281,"cacheCreationInputTokens":2938430,"webSearchRequests":0,"costUSD":100.43402300000021,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","origin":{"kind":"task-notification"},"subagent_stats":{"spawned":13,"requested":{"background":0,"foreground":0,"unset":13},"started_in_background":13,"max_depth":1,"spawned_by_subagents":0,"completed":13,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{"Explore":13}},"subtype":"success","api_error_status":null,"result":"Der Lauf ist abgeschlossen. Alle sieben Ergebnisdateien liegen im vorgegebenen Verzeichnis, die analysierte Codebasis ist unverändert (git status leer).\n\n## Ergebnis\n\n**Spezifikation (172 Anforderungen, durchgängig im vorgegebenen Format mit Fakt/Aussage-Trennung und klassifizierten Belegen):**\n- **StRS.md** – 27 Stakeholder-Anforderungen inkl. Akteurstabelle und belegter Abgrenzungen (z. B. keine Mahngebühren, Barbelege blockiert)\n- **SyRS.md** – 70 System-Anforderungen (Architektur/APIs, Sicherheit, Belegwesen, Service, Lager/RMA, Finanzen, Integrationen; NFAs mit ISO-25010-Zuordnung, u. a. ein konsolidierter Härtungskatalog SyRS-055)\n- **SwRS.md** – 75 Software-Anforderungen (Schichtenmodell, Persistenzkonventionen, Statusmaschinen, Rechenkerne, 15 als `belegt; Workaround` markierte historische Sonderlösungen)\n- **Traceability.md** – vollständige Matrix StRS↔SyRS↔SwRS mit je einem repräsentativen PRIMÄR-Beleg pro Zeile\n- **Hypothesen.md** – 20 Hypothesen mit offenen Validierungsfragen (u. a. Hersteller-Telemetrie/Datenschutz, nie geprüftes Recht CHANGE_VISIBILITY, gewachsene Toleranzwerte 2,00/3,00/0,50 €)\n- **Glossar.md** – ~120 Domänenbegriffe\n- **Analysebericht.md** – Modulübersicht mit Analysetiefe, Konsistenzcheck und Selbstbewertung\n\n**Vorgehen:** Nach Struktur- und Doku-Sichtung habe ich die technische Analyse über 13 parallele Explorationsdurchgänge (Claude-Code-Standard-Subagenten, keine Agentendateien/MCP) über die Fachdomänen gefahren, deren belegte Findings im Scratchpad gesichert und zentral zu den drei Ebenen formalisiert.\n\n**Konsistenzcheck (im Analysebericht dokumentiert):** IDs eindeutig und lückenlos; keine Anforderung ohne Beleg; beim Check fand ich zwei fehlerhafte Abwärts-Tracelinks (SyRS-063, SyRS-066) und habe sie vor Abgabe korrigiert — danach zeigen alle Verweise auf existierende IDs.\n\n**Ehrliche Grenzen:** Nicht analysiert blieben u. a. VoucherManagement, CashBook, Provisionsdetails, die 371 NamedQueries einzeln, Reportinhalte und mehrere Nebenmodule (Chat, Mailings, Mobile) — im Analysebericht als Abdeckungslücken mit konkreten Nachschlag-Empfehlungen für Folge-Iterationen ausgewiesen. Zeilenangaben in Belegen sind „ca.\"-Angaben zum Commit-Stand 79c1142f48; maßgeblich sind Klasse/Methode.","ttft_ms":8554,"ttft_stream_ms":2530,"time_to_request_ms":18,"type":"result","duration_ms":3116319,"uuid":"65721d91-e638-4715-b901-58210d3aa500","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 27 | 15,7 % |
| SyRS | 70 | 40,7 % |
| SwRS | 75 | 43,6 % |
| **Gesamt** | **172** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 79 | 45,9 % |
| Sicherheit | 23 | 13,4 % |
| Schnittstelle | 19 | 11,0 % |
| Daten | 9 | 5,2 % |
| funktional (Daten) | 4 | 2,3 % |
| funktional (Komponente) | 4 | 2,3 % |
| nicht-funktional (Produktsteuerung) | 2 | 1,2 % |
| funktional / Sicherheit | 2 | 1,2 % |
| Schnittstelle (Zahlungsverkehr) | 2 | 1,2 % |
| funktional (Geschäftsziel) | 1 | 0,6 % |
| (27 weitere) | 27 | 15,7 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 331 |
| davon `PRIMÄR` | 314 (94,9 %) |
| davon `SEKUNDÄR` | 5 (1,5 %) |
| davon `KONTEXT` | 12 (3,6 %) |
| Belege je Anforderung (Median) | 2,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 172 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 169 | 98,3 % |
| als `HYPOTHESE` gekennzeichnet | 3 | 1,7 % |
| als Workaround vermerkt | 15 | 8,7 % |
| Konsolidierungskandidaten | 17 | 9,9 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (58 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 172 von 172 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_220735_fable5_builtin_ehigh_v3.7.0-15db\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T23:10:36.1728701+02:00
@@ -0,0 +1 @@
2026-08-25T22:07:48.6486301+02:00
@@ -0,0 +1,129 @@
# Analysebericht – RRE-Lauf V1/Iteration 01
**Untersuchungsgegenstand:** Gesamte Codebasis `C:\DEV\MasterArbeit\QuellCode\CentronERP` (Branch main, Commit 79c1142f48, Arbeitsstand 2026-08-25)
**Methode:** Statische Analyse ohne Ausführung, RRE-Methodenkette Schritte 2–6 (Scope in Schritt 1 vorgegeben: gesamte Codebasis; Schritt 7 Validierung erfolgt extern)
**Werkzeug:** Claude Code ohne Agentendateien/MCP (Prompt-only-Baseline)
---
## 1. Systemsteckbrief (Ergebnis der Artefakterhebung, Schritt 2)
| Merkmal | Befund | Beleg |
|---|---|---|
| Produkt | „NEXOWARE c-entron ERP" (c-entron.NET), Hersteller NEXOWARE Systems GmbH | Directory.Build.props |
| Version | 2.0.2611-alpha (Nerdbank GitVersioning) | version.json |
| Plattform | .NET 10 (SDK 10.0.100); WPF-Client net10.0-windows; WebService net10.0 (Windows HTTP.sys / Linux Kestrel, Docker vorhanden) | global.json, csproj-Dateien, docker/ |
| UI-Technologie | WPF mit DevExpress (Client), Blazor mit DevExpress (Nexus) | DevExpress.Version.props, README.md |
| Persistenz | MSSQL; NHibernate; Legacy-Tabellen deutsch (AufKopf, RechPos, Kunden, hlpdsk_requests …), moderne Views englisch; Migration über 764 nummerierte C#-Skripte | docs/reference/receipts/receipts-backend-architecture.md, ScriptMethods/ |
| Umfang | 15.554 C#-Dateien, 1.233 XAML-Dateien, 491 Razor-Dateien; 97 BL-Fachbereiche; 88 Entitäts-Fachordner | Zählung per find/ls |
| Schnittstellen | RPC-Dienst ICentronRestService (29 Teilbereiche), REST-API v1 (41 Controller), 4 SignalR-Hubs, ~40 anmeldefähige Anwendungen | Centron.Host/Services, Centron.Controllers, ApplicationKind.cs |
| Externe Anbindungen | GLS, Shipcloud, FinAPI, ITscope, Icecat, ebInterface, EGIS, COP, docuFORM, EDI-Distributoren (ALSO, Alltron, Herweck, Komsa, OpenTrans), DATEV, Exchange, TAPI, RMM (NAble, GFIMax u. a.), DocBee, TANSS | src/apis, ApplicationKind.cs, edi-architecture.md |
| Berechtigungen | ~750 Rechtekonstanten, Gruppenmodell, einschränkende Rechte („nur eigene [Filiale]") | UserRightsConst.cs, CentronRights.md |
| Lizenzierung | GUID-Lizenzen mit count/valid-until/version; Modul- und Login-Gates; Startabbruch ohne Lizenz | licensing-system.md, ModuleRegistration.cs, CentronHost.cs |
| Konfiguration | ~500 ApplicationSettings, 91 Einstellungsseiten, persönliche Einstellungen | ApplicationSettingID.cs, ModuleRegistration.cs |
| Sprachen | Deutsch führend, Englisch als Zweitsprache (resx-Paare); DACH-Spezifika (ESR Schweiz, ebInterface AT, XRechnung DE) | general-structure.md, resx-Dateien |
## 2. Vorgehensdokumentation (Schritte 2–6)
- **Schritt 2 – Artefakterhebung:** Repositorystruktur, Projektdateien, 55 Doku-Dateien unter docs/ (Architektur-, DB-, Sicherheits-, Feature-Dokumentation), CentronRights.md, README, Build-/Deploy-Artefakte (azure/, docker/, deployment/), Git-Historie (jüngste Commits als KONTEXT-Belege). Keine SQL-Dateien im Repo – Schema ergibt sich aus Skriptsystem, Mappings und Doku.
- **Schritt 3 – Technische Analyse:** Modulinventar aus ModuleRegistration.cs (84 Registrierungseinträge, davon 1 Testmodul, 1 auskommentiert „Reisekosten"); Statusmaschinen (ReceiptState, WebReceiptState, BarcodeState, DunningLevel, EDI-/RMA-/Produktions-Status, konfigurierbare Helpdesk-Status); Validierungslogik (SaveReceipt-Pipeline mit >30 benannten Prüfungen); Berechtigungsprüfungen (UI-Gate, BL-Prüfmuster, API-Attribute); Abhängigkeiten (Schichtenmodell, Dual-Access BL/WS).
- **Schritt 4 – Semantische Interpretation:** Technische Beobachtungen wurden in fachliche Soll-Aussagen überführt (Feld `Fakt` → Feld `Aussage` je Anforderung); Beispiele: Negativbuchungs-Login → Vier-Augen-Freigabe; InternalInvoice-Nummernkreis → getrennte 0,00-Dienstleistungsrechnungen; GetClosedHelpdeskState → konfigurierbare Abschlusssemantik.
- **Schritt 5 – Formalisierung:** 207 Anforderungen im vorgegebenen Format (35 StRS, 84 SyRS, 88 SwRS) mit Vorbedingung, Fakt, Aussage, Ergebnis, Prüfidee.
- **Schritt 6 – Traceability:** Vollständige Aufwärtsverkettung (SwRS→SyRS→StRS) in den Dokumenten; konsolidierte Matrix in Traceability.md inkl. Lückenliste (27 SyRS ohne SwRS-Verfeinerung).
## 3. Modul-/Komponentenübersicht mit Analysetiefe
Legende Tiefe: **T** = tief (Kernlogik gelesen), **S** = stichprobenhaft (Signaturen/Struktur/Doku), **E** = nur Existenz erfasst, **–** = nicht analysiert.
| Fachbereich / Komponente | Tiefe | Bemerkung |
|---|---|---|
| Belegwesen-Kern (ReceiptBL: Speicherpipeline, Nummern, Versionen, Storno, Kreditlimit, Sperren, Ordner) | T | ca. 800 von 11.441 Zeilen gezielt gelesen; Prüfkatalog vollständig erfasst |
| Bestands-/Artikelbuchung, Negativbuchung (ReceiptArticleBookingBL) | T | Entscheidungskette vollständig |
| Seriennummern/Barcodes (BarCode, BarcodeState, ReceiptBarcodeBL-Aufrufe) | T/S | Statusmodell vollständig; ReceiptBarcodeBL selbst nur über Aufrufstellen |
| Nummernkreise (NumberGroupEnum/BL) | T | inkl. Eindeutigkeitsprüfung |
| Rechte-/Lizenzsystem, Modulregistrierung | T | Rechtekatalog strukturell, 84 Modul-Gates vollständig |
| Authentifizierung (Host-Auth, Tickets, JWT/OIDC, 2FA, Passwörter) | T | UsersBL/TwoFactorBL/JwtAuthController gelesen; Authenticator-Pipeline nicht (H-12) |
| Verträge & automatische Abrechnung (ReceiptContract, AutomaticFacturaBL) | T/S | Datenmodell+Doku tief, BL auf API-Ebene; Berechnungsinnereien nicht |
| Vereinfachte Ticketabrechnung (TimerBillingBL) | S | API-Ebene, Rechteprüfung verifiziert |
| Helpdesk (Entitäten, Close, Historie), Eskalation | T | CloseBL und EscalationBL gelesen |
| Zeiterfassung (HelpdeskTimerBL) | T | Speicherlogik inkl. KI-Kopplung |
| Mahnwesen (DunningBL) | T/S | Stopp-/Einstellungslogik gelesen; DunningRunBL nicht |
| OPOS, Zahlungseingang, SEPA | S | Struktur/Module/Konditionen; Lauflogik nicht |
| Online-Banking (FinAPI) | S | Methodenkatalog vollständig, Interna nicht |
| FIBU-Export/DATEV, Kontenfindung | S | Exportstatus + Aufrufstellen |
| E-Rechnung ZUGFeRD/XRechnung | S | Doku (Feldmapping) + Dateibestand; XML-Code nicht gelesen |
| EDI Distributoren | S | Architektur-Doku + Statusenums; Parser (Gateway) nicht |
| Einkauf (Lieferantenbelege, Bestellvorschlag) | S | Nummernkreise, BL-Ordner, Vorschlags-API |
| Lager (Stock/StorageArea), Inventur, Kommissionierung | S | Inventur-API gelesen; Buchungsdetails über ReceiptArticleBookingBL |
| Versand GLS/Shipcloud | S | API-Projekte + Einstellungen |
| Kassenbuch/Barverkauf | S | Buchungs-API; Blockade im neuen Speicherweg verifiziert |
| Provisionen | S | Datenmodell vollständig, Berechnung nicht |
| Nexus ServiceBoard/Kundenportal/WebCart/WebOffer | S | vollständige Routeninventur; einzelne Komponenten (SignaturePad) identifiziert |
| WebAccounts | S | BL-Struktur + Passwortpfad |
| REST-API | S | Controllerliste vollständig; 2 Controller im Detail |
| RPC-Dienst (ICentronRestService) | E | 29 Teilbereiche inventarisiert, Methoden nicht |
| Mail/Vorlagen, MailScanner, Kalender/Exchange, TAPI | S/E | Vorlagenmodell tief (Dunning), Scanner/Sync nur strukturell |
| Projekte (CRM/Ticket), Produktion, MSP/RMM, DSGVO | S/E | Struktur, Statusenums, Module |
| Reporting/Statistiken, ReportEngine, Reportserver | E | Module+BL-Existenz |
| Change-Tracking/Logs (ChangeLog, AnlageLog, ReceiptLog, TimerLog) | T/S | Datenmodelle + Schreibstellen |
| Einstellungen (Settings-System) | S | Katalogumfang; einzelne Settings punktuell |
| Tests (EndToEnd/Integration/Playwright) | E | als Verifikationsquelle notiert, Inhalte nicht analysiert |
| DocuBoard, Chats, SocialMedia, VideoPortal, Riversuite-Familie, PasswordManager-Interna, TradePool, VoucherManagement, IndexSearch, MassUpdate, Mobile-Altmodelle, Tags, WebLinks, SelfCare, ExternalHelpdesk | E/– | nur Namensinventar; keine Anforderungen abgeleitet (bewusste Lücke) |
| XAML-Masken des WPF-Clients (1.233 Dateien), Reports/Drucklayouts | – | nicht analysiert; für maskenbezogene Pflichtfeld-/Redundanzanalyse erforderlich |
| Gateway-Bibliotheken (EDI-Parser), assemblies/, nugets/ | – | Binär-/Fremdanteile |
## 4. Konsistenzcheck über das Anforderungs-Set (Ergebnis)
Durchgeführt per Skriptprüfung über die erzeugten Dokumente (2026-08-25):
| Prüfung | Ergebnis |
|---|---|
| Doppelte oder mehrfach vergebene IDs | **0 Duplikate** (35 StRS + 84 SyRS + 88 SwRS = 207 eindeutige IDs) |
| Anforderungen ohne Beleg | **0** (207/207 mit Belege-Abschnitt; 336 Einzelbelege) |
| Anforderungen ohne Prüfidee/Status/Tracelinks/Konsolidierung | **0** (je 207/207) |
| Tracelinks auf nicht existierende IDs | **0** (alle referenzierten StRS-/SyRS-/SwRS-IDs liegen in den gültigen Bereichen; geprüft über alle 5 Dokumente inkl. Traceability und Hypothesen) |
| Referenzierte Hypothesen-IDs | alle definiert (H-02, H-03, H-04, H-08, H-12 referenziert; H-01…H-16 vorhanden) |
| Forward-Traceability StRS→SyRS | vollständig (alle 35 StRS haben mindestens eine SyRS-Verfeinerung) |
| Forward-Traceability SyRS→SwRS | 57 von 84 SyRS verfeinert; 27 offene in Traceability.md Abschnitt 2 ausgewiesen |
## 5. Kennzahlen des Anforderungs-Sets
| Kennzahl | Wert |
|---|---|
| Anforderungen gesamt | 207 (StRS 35, SyRS 84, SwRS 88) |
| Einzelbelege | 336 – davon PRIMÄR 299 (89 %), SEKUNDÄR 30 (9 %), KONTEXT 7 (2 %) |
| Status „belegt" ohne Einschränkung | 189 |
| Status „belegt" mit Einschränkungsvermerk | 13 |
| Status „belegt; Workaround" | 4 (SHA1-Hashing, Barbeleg-Blockade, Doppel-Speicherweg, StRS-032) |
| Status „HYPOTHESE" | 1 (SyRS-009 Kontosperrung – Durchsetzung unbelegt) |
| Externe Hypothesen (Hypothesen.md) | 16 (H-01…H-16) |
| Konsolidierungskandidaten | 17 markierte Felder (u. a. Adressstamm vs. CRM; Kunden- vs. Accounts-Modell; drei Abrechnungswege; RPC vs. REST; WPF-Ticketliste vs. ServiceBoard; SHA1-Ablösung; Doppel-Speicherweg; WebPassword vs. WebAccount; CRM- vs. Ticket-Projekte; Rechtekonstanten-Ablageort) |
## 6. Selbstbewertung
### 6.1 Was wurde vollständig, was stichprobenhaft, was gar nicht analysiert?
- **Tief analysiert** (Kernlogik gelesen, PRIMÄR-Belege auf Methodenebene): Belegwesen-Speicherweg inkl. aller Prüfungen, Bestands-/Seriennummernbuchung, Nummernvergabe, Rechnungsstorno, Kreditlimit, Beleg-Sperren/-Versionierung, Rechte-/Lizenz-Gates, Anmeldeverfahren (ohne Authenticator-Pipeline), Passwort-/2FA-Logik, Helpdesk-Abschluss, Eskalation, Zeiterfassung, Mahnstopplogik, Vertrags-/Zählerabrechnungs-API, Host-/Startsequenz, Migrations- und Einstellungssystem.
- **Stichprobenhaft:** Einkauf, Lager-Randprozesse (Inventur, Kommissionierung), Finanzen-Läufe (OPOS/SEPA/Zahlungseingang), E-Rechnung, EDI, Versand, Provisionen, Portale (Routen statt Verhalten), REST-API (2 von 41 Controllern), Kassenbuch, Projekte, MSP, DSGVO, Kalender/TAPI/MailScanner.
- **Gar nicht:** WPF-XAML-Masken (1.233 Dateien) und damit die maskenspezifische Feld-/Pflichtfeld-Redundanz; Reports/Drucklayouts; RPC-Methodeninventar; Gateway-EDI-Parser; Randmodule (DocuBoard, SocialMedia, VideoPortal, Riversuite-Familie, PasswordManager-Interna, TradePool, VoucherManagement u. a.); Testinhalte; DB-Instanz selbst (kein Zugriff – Schemaaussagen stützen sich auf Code/Doku).
### 6.2 Wo war der Beleg dünn?
- **KONTEXT-/SEKUNDÄR-lastig:** WebCart-Sortimentsregel (nur README), Timer-Billing-Datumsrecht (nur Commit-Message), automatische Ticketerstellung (Feature-Doku + Entität), C-Sign-Zusammenhang (Commit + Enum + UI-Dateien).
- **Struktur- statt Verhaltensbelege:** MailScanner, Exchange-Sync, Produktion, DSGVO-Umfang, MSP-Collector, Provisionsberechnung, OutlookAddIn – hier belegen Dateien/Module die Existenz, nicht die Regeln (entsprechende Einschränkungsvermerke im Status bzw. Hypothesen H-05…H-15).
- **Herabgestuft:** SyRS-009 (Kontosperrung) auf HYPOTHESE, da die Durchsetzung im Login nicht nachgewiesen ist (Sicherheitsanforderung ohne PRIMÄR-Beleg der Prüfung).
- **Bekannte Beleg-Grenze:** Zeilenangaben referenzieren den analysierten Commit-Stand; die Doku-Dateien unter docs/ sind teils KI-generiert entstanden (Hinweis „ai-codebase-navigation.md" im Repo) – wo möglich wurden Doku-Aussagen gegen Code verifiziert (z. B. Belegarchitektur, Lizenzsystem), sonst als SEKUNDÄR eingestuft.
### 6.3 Erkenntnisse für eine Folge-Iteration (priorisiert)
1. **SwRS-Verfeinerung der 27 offenen SyRS** (Traceability Abschnitt 2), vorrangig Finanzen-Läufe (OPOS/Dunning-Run/SEPA), EDI-Verarbeitung und E-Rechnungs-Import (Abrechnungs-/Compliance-Risiko).
2. **Hypothesenklärung H-01…H-16**, vorrangig H-02 (Salt), H-03 (GoBD-Festschreibung), H-12 (Kontosperrungs-Durchsetzung), H-16 (REST vs. RPC-Abdeckung) – alle sicherheits- bzw. architekturentscheidend für die SaaS-Neuimplementierung.
3. **Maskeninventar WPF (XAML) + ICentronRestService-Methodeninventar** maschinell erzeugen, um (a) die im Prompt vermutete maskenbezogene Redundanz systematisch zu finden und (b) das API-Zielbild zu dimensionieren.
4. **Preisfindung als eigener Analyseblock** (ActionPriceBL, ArticleVolumePrices, Sonderpreise, Projektpreise, ReceiptPriceHelperBL, CalculationUtils): hohe fachliche Dichte, bisher nur gestreift – für ein Verkaufssystem zentral.
5. **End-to-End-Tests als Verhaltensorakel** auswerten (tests/Centron.Tests.EndToEnd): Sie führen laut Doku DB-Skripte aus, speichern über ReceiptWebServiceBL und prüfen Legacy-Tabellenwerte – ideale Quelle zur Verifikation der hier formulierten Prüfideen.
6. **Datenmodell-Gesamtkatalog** aus Centron.DAO-Mappings generieren (Tabellen-/Spalteninventar), um Datenanforderungen vollständig und DB-unabhängig zu belegen.
7. **Konsolidierungsentscheidungen vorbereiten:** Die 17 markierten Kandidaten (insb. drei Abrechnungswege, zwei Kundenmodelle, zwei API-Kanäle, zwei Ticket-Frontends) sind Architekturentscheidungen der Neuimplementierung und sollten vor weiterer Detailspezifikation fachlich entschieden werden.
### 6.4 Einschätzung der Belastbarkeit
Das Set deckt die abrechnungs-, sicherheits- und berechtigungskritischen Kernpfade mit PRIMÄR-Belegen auf Code-Zeilenebene ab (89 % PRIMÄR-Anteil) und erfüllt die Konsistenzkriterien vollständig. Für eine Web-/SaaS-Neuimplementierung ist es als Ausgangsbasis belastbar; die ausgewiesenen Lücken (Abschnitt 6.1/6.3) und Hypothesen sind explizit und adressierbar. Nicht geeignet ist der Stand als abschließende Spezifikation für die dort genannten Randmodule und für maskengebundene Detailregeln.
@@ -0,0 +1,63 @@
# Glossar
Domänenbegriffe der c-entron ERP-Suite, wie sie in StRS/SyRS/SwRS verwendet werden. Technische Bezeichner (Klassen, Tabellen, Spalten) bleiben in Originalsprache. Jeder Begriff ist mit dem Artefakt belegt, aus dem er abgeleitet wurde.
| Begriff | Definition | Artefaktbezug |
|---|---|---|
| **Beleg (Receipt)** | Oberbegriff für kaufmännische Dokumente der Verkaufs- und Einkaufskette (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag sowie Lieferanten-Pendants). Alle Belege erben von `ReceiptBase`. | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` |
| **Belegkopf / Belegposition** | Zweiteilige Belegstruktur: Kopftabelle (`*Kopf`, z. B. `AufKopf`) mit Metadaten und Positionstabelle (`*Pos`, z. B. `AufPos`) mit Einzelpositionen. | `docs/reference/receipts/receipts-backend-architecture.md` |
| **Belegversion** | Vollständiger Schnappschuss eines Belegs (Kopf und Positionen) in `*KopfVersions`/`*PosVersions`-Tabellen; jede inhaltliche Änderung erzeugt eine neue Version mit fortlaufender Versionsnummer. | `ReceiptBL.SaveReceipt` (Versionsnummernprüfung), `docs/reference/receipts/receipts-backend-architecture.md` |
| **Belegstatus** | Zustand eines Belegs: `offen` (Active=1), `abgeschlossen` (Completed=2), `storniert` (Canceled=3). | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| **Belegweitergabe (Forwarding)** | Überführung eines Belegs in einen Folgebeleg (z. B. Auftrag → Lieferschein → Rechnung); Positionen tragen dazu einen Ursprungsverweis (`IReceiptItemWithOrigin`). | `ReceiptBL.GetReceiptForwardedInto`, `ReceiptArticleBookingBL.UpdateOrigin` |
| **Nummernkreis (NumberGroup)** | Konfigurierbarer Zahlenbereich zur Vergabe fortlaufender Nummern je Belegart bzw. Objekt (31 definierte Kreise, u. a. Angebot, Auftrag, Rechnung, Kunde, Helpdesk), optional filialspezifisch. | `src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs`, `NumberGroupBL.GetNextNumber` |
| **I3D** | Standard-Primärschlüsselspalte aller Tabellen (`int IDENTITY(1,1)`, „ID 3develop"); Fremdschlüssel enden auf `...I3D`. | `docs/guides/database/database-conventions.md` |
| **Mandant (Mandator)** | Oberste Organisationseinheit (rechtliche Firma) des Systems; Filialen sind Mandanten zugeordnet. | `src/backend/Centron.Entities/Entities/Administration/Company/Mandator.cs`, `Branch.MandatorI3D` |
| **Filiale (Branch)** | Organisatorische Untereinheit eines Mandanten mit eigener Adresse, Buchhaltungsnummer und optional eigenen Nummernkreisen; viele Rechte kennen „nur eigene Filiale"-Einschränkungen. | `src/backend/Centron.Entities/Entities/BranchArea/Branch.cs`, `CentronRights.md` |
| **Recht (UserRight)** | Ganzzahlig identifizierte Berechtigung (ca. 750 Konstanten), die Benutzern über Gruppen zugeordnet wird; es existieren gewährende und **einschränkende Rechte** („nur eigene", „nur eigene Filiale"). | `src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs`, `CentronRights.md` |
| **Lizenz (License)** | Per GUID identifiziertes, kundenbezogenes Freischaltmerkmal mit optionalem `count`, `valid until date`, `valid until version`; steuert Sichtbarkeit von Modulen und Anmeldefähigkeit von Anwendungen. | `docs/reference/security/licensing-system.md`, `LicenseManager` |
| **Anwendung (ApplicationKind)** | Am WebService anmeldefähige Client-Anwendung (z. B. c-entron ERP, c-entron Nexus, Service-Board, Outlook Add-In, MailScanner, WebCart); je Anwendung Lizenz-GUID, Ablaufverhalten und ggf. erforderliches/verbietendes Recht. | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| **Helpdesk / Ticket** | Servicevorgang (Störung, Anfrage) zu einem Kunden mit konfigurierbarem Status, Priorität, Kategorie, Typ, Fälligkeit, Bearbeitern und Historie; Tabelle `hlpdsk_requests`. | `src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs`, `NumberGroupEnum.Helpdesk` |
| **Helpdesk-Zeit (HelpdeskTimer)** | Auf ein Ticket erfasste Arbeitszeit mit Start/Stopp, Pausenzeit, Zeittyp, Abrechenbarkeit (`Calculable`), Abrechnungsstatus und optionaler Kundensignatur. | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskTimerArea/HelpdeskTimer.cs` |
| **Eskalation** | Zeitgesteuerte, bis zu dreistufige Benachrichtigung zu offenen Vorgängen unter Berücksichtigung von Arbeitszeitfenstern und Wochenendregeln. | `src/backend/Centron.BL/Sales/Support/Escalation/EscalationBL.cs` |
| **Vertrag (ReceiptContract)** | Beleg für wiederkehrende Leistungen mit Abrechnungsintervall (`BillingIntervalKind/Duration`), automatischer Abrechnung, Kontingenten, Zählern und Laufzeit-/Kündigungsfeldern; Tabellen `VertragKopf`/`VertragPos`. | `docs/reference/receipts/contracts-backend.md` |
| **Kontingent** | In einem Vertrag vereinbartes Stunden- oder Wertbudget, dessen Verbrauch fortgeschrieben und ggf. über einen Ausgleichsartikel abgerechnet wird. | `ReceiptContract`-Felder `ContingentUsed*`, `ReceiptContractBL.ContractContingentBalanceCalculation` |
| **Zähler-/Klickabrechnung** | Verbrauchsabrechnung (z. B. Drucker-Klicks) über Zählerstände je Gerät mit Freimengen und Staffelpreisen. | `AutomaticFacturaBL.Contracts.cs` (`GetCounterFreeCount`, `GetCounterScalePrices`) |
| **Stammblatt (MasterDataList)** | Kundenbezogene Geräte-/Bestandsliste, u. a. zur Verknüpfung von Geräten mit Verträgen. | `UserRightsConst.Sales.Customer.CustomerCommon.SHOW_MASTERDATALIST`, `AutomaticFacturaBL.GetMasterDataList` |
| **Barcode / Seriennummer** | Einzelstück-Identifikation eines Artikels mit eigenem Lebenszyklusstatus (`BarcodeState`, z. B. InStock, InOrder, InInvoice, Scrapped) und Verweisen auf Belegpositionen. | `src/backend/Centron.Entities/Entities/Warehousing/BarCode.cs`, `src/backend/Centron.Interfaces/Warehousing/BarcodeState.cs` |
| **Negativbuchung** | Lagerbuchung, die den Bestand unter null senkt; nur mit Recht `RIGHT_NEGATIVBUCHUNG` bzw. Freigabe durch berechtigten Kollegen zulässig. | `ReceiptArticleBookingBL.UpdateStock` |
| **OPOS** | Offene-Posten-Verwaltung (unbezahlte Rechnungen/Gutschriften) als Grundlage von Zahlungszuordnung und Mahnwesen. | `src/backend/Centron.BL/Sales/Receipts/Invoices/Opos/OposBL.cs` |
| **Mahnstufe (DunningLevel)** | Eskalationsstufe des Mahnwesens: None, Level1–Level3; je Kunde/Beleg per Mahnstopp (befristbar) aussetzbar. | `src/backend/Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs`, `DunningBL.GetDunningStopActive` |
| **Zahlungskondition (AssetCondition)** | Konfigurierbare Zahlungsbedingung mit bis zu drei Skontostufen, Fälligkeitsregeln (`DueKind`, `DuePlusDays`, `DueAtDay`, `DuePlusMonths`) und Zuordnung zu Belegarten. | `src/backend/Centron.Entities/Entities/Administration/MasterData/AssetCondition.cs` |
| **Skonto** | Prozentualer Preisnachlass bei Zahlung innerhalb einer Frist (bis zu 3 Stufen je Zahlungskondition). | `AssetCondition.Skonto1OffDay/Skonto1Percent` u. a. |
| **SEPA-Mandat** | Einzugsermächtigung eines Kunden für SEPA-Lastschriften; Belege können ein Mandat referenzieren (`MandatI3D`), Pflicht abhängig von Zahlungskondition. | `ReceiptBL.CheckIfMandatIsNeeded`, `docs`-Modul „SEPA" (`PaymentTransactionAppModuleController`) |
| **FIBU-Export** | Übergabe von Belegen an die Finanzbuchhaltung (u. a. DATEV Belegtransfer); exportierte Belege gelten als „an die Buchhaltung übergeben". | `src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs` |
| **E-Rechnung (ZUGFeRD/XRechnung)** | Strukturierte elektronische Rechnung; Erzeugung in ZUGFeRD 1.0/2.0/2.1 bzw. XRechnung bis 3.0.1 aus Rechnungs-/Gutschriftsdaten. | `docs/reference/zugferd-field-mapping.md`, `InvoiceZugferdBL.cs` |
| **EDI** | Elektronischer Belegaustausch mit Distributoren (ALSO, Alltron, Herweck, Komsa, OpenTrans): Bestellungen, Auftragsbestätigungen, Lieferavis, Rechnungen. | `docs/reference/edi/edi-architecture.md`, `SupplierEdiBL.*` |
| **WebAccount** | Anmeldekonto eines Endkunden für Web-Angebote (Kundenportal, WebCart); getrennt vom internen `AppUser`. | `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs`, `README.md` (WebCart) |
| **WebOffer / C-Sign** | Web-basierte Bereitstellung eines Angebots an Endkunden inkl. Annahme, Änderungswünschen, Ablehnung und digitaler Signatur; Statusmodell `WebReceiptState`. | `src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs`, `src/nexus/CentronNexus/WebOffer/` |
| **ServiceBoard (Nexus)** | Blazor-Weboberfläche für Servicemitarbeiter (Ticketlisten, Kanban, Planung, Kundencockpit, Zeiterfassung). | `src/nexus/CentronNexus/ServiceBoard/` (Routen `/serviceboard/...`) |
| **Kundenportal (Customer Portal)** | Nexus-Bereich für Endkunden: eigene Tickets, Belege, Dokumente, Formulare. | Routen `/customerportal/...` in `src/nexus/CentronNexus` |
| **MyDay** | Persönliche Tages-/Auslastungsplanung der Mitarbeiter mit Import aus Zeiterfassung. | `MyDayEditorAppModuleController`, `MyDayBL.TryUpdateWorkItemFromHelpdeskTimer` |
| **Erwartete Events (Expected Events)** | Überwachungsmodul, das das Eintreten erwarteter Ereignisse (z. B. Datenlieferungen) prüft und auswertet. | `ExpectedEventsAppModuleController`, `src/backend/Centron.BL/ExpectedEvents/` |
| **MSP** | Managed-Service-Provider-Geschäft; Module MSP-Collector/-Auswertung/-Dashboard aggregieren Abrechnungsdaten externer RMM-/Cloud-Dienste zur Vertragsabrechnung. | `MspCollectorAppModuleController`, `AutomaticFacturaBL.CreateSpecialArticleToContractFromMspEvaluation` |
| **RMM** | Remote Monitoring & Management; externe Systeme, deren Nutzungsdaten (z. B. Gerätezahlen) in Vertragsabrechnungen einfließen. | `docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md`, `RmmController.cs` |
| **RMA** | Rücksendungs-/Reparaturabwicklung (Werkstatt) mit eigenen Nummernkreisen (RMA, Reparatur, Reparatureingang, Rücksendung). | `NumberGroupEnum` (RMANumber, Repairing, RepairEntrance, Reshipment), `RmaOverviewAppModulController` |
| **Kommissionierung** | Zusammenstellung bestellter Ware zu Aufträgen im Lager; Teil-Kommissionierungsaufträge mit eigenem Status. | `PartialCommissionOrderState.cs`, `OrderCommissionAppModuleController` |
| **Inventur** | Bestandsaufnahme je Lager mit Inventurgruppen, Lagerabschluss und Verlustbuchung von Seriennummern. | `src/backend/Centron.BL/Warehousing/InventoryManagement/InventoryBL.cs` |
| **Kassenbuch** | Erfassung von Barzahlungsvorgängen; Zahlungskonditionen können Kassenbuchwirkung haben (`ChangesCashBook`). | `src/backend/Centron.BL/Sales/CashBooks/`, `AssetCondition.ChangesCashBook` |
| **Provisionsschema** | Regelwerk zur Ermittlung von Vertriebsprovisionen mit Kundenzuordnung, Mitarbeiterzielen und -stufen. | `ReceiptProvisionSchema*.cs`, `ProvisionSchemaManagementAppModuleController` |
| **Belegsperre (AssetLock)** | Pessimistische Sperre eines Belegs durch das Kurzzeichen des bearbeitenden Mitarbeiters (`Lockuser`), um parallele Bearbeitung zu verhindern. | `src/backend/Centron.BL/Sales/CustomerAssets/AssetLockBL.cs` |
| **ConcurrencyControlGuid** | GUID je Belegversion zur optimistischen Konfliktkontrolle beim Speichern. | `ReceiptBase.ConcurrencyControlGuid`, `ReceiptBL` (Vergleich beim Speichern) |
| **ChangeLog** | Objektbezogenes Änderungsprotokoll mit Eigenschaft, Alt-/Neuwert, Benutzer und Zeitpunkt. | `src/backend/Centron.Entities/Entities/ChangeTracking/ChangeLog.cs` |
| **AnlageLog** | Gemeinsames Belegprotokoll aller Belegarten, unterschieden per `AnlageArt` (1=Angebot … 22=Vertrag). | `docs/reference/receipts/receipts-backend-architecture.md` |
| **ObjectKind (CentronObjectKindNumeric)** | Systemweite numerische Typkennung für Objektarten (214 Einträge), verwendet für polymorphe Verweise (`ObjectI3D` + `ObjectKind`). | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` |
| **Skript (ScriptMethod)** | Nummeriertes Datenbank-Migrationsskript in C# (`ScriptMethod<Nr>`), das beim Start des WebService ausgeführt wird; 764 Skripte im Stand der Analyse. | `src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/`, `docs/guides/database/create-scripts.md` |
| **Einstellung (ApplicationSetting)** | Zentral verwaltete Konfigurationswerte (ca. 500 IDs) für fachliche und technische Optionen. | `src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs` |
| **Sonderpreis (SpecialPrice/Sonderpreise)** | Kundenindividuelle Artikelpreise; im WebCart bestimmen sie das für den Endkunden sichtbare Sortiment. | `README.md` (WebCart), `CustomerSpecialArticleBL.cs` |
| **Textbaustein** | Wiederverwendbarer Textblock für Belege und Kommunikation. | `TextBlockManagementAppModuleController` |
| **Vereinfachte Ticketabrechnung (TimerBilling)** | Modul zur gesammelten Abrechnung erfasster Ticketzeiten in Rechnungen/Lieferscheine ohne Einzelbelegpflege. | `src/backend/Centron.BL/Sales/CustomerAssets/TimerBilling/TimerBillingBL.cs` |
| **Pauschalabrechnung (FlatRate)** | Abrechnung von Projekten/Leistungen zu Pauschalen. | `FlatRateProjectAppModuleController` |
| **DATEV Belegtransfer** | Übertragung von Belegdaten/-bildern an DATEV Online. | `DatevOnlineAppModuleController`, `Modules.DataExchange.DatevOnline2020` |
| **DSGVO-Modul** | Funktionen zur Erfüllung von Datenschutzanforderungen (z. B. Auskunft/Löschung, Auftragsverarbeitungsverträge). | `CentronDataSecurityAppModuleController`, `OrderProcessingContractState.cs` |
| **Zwei-Faktor-Authentifizierung (2FA)** | Zusätzliche PIN-Prüfung je Benutzer mit hinterlegtem Geheimschlüssel und Gültigkeitsdauer in Tagen. | `TwoFactorAuthenticationBL.cs`, `AppUser.UseTwoFactorAuthentication` |
| **Access Token** | Persönlicher API-Zugriffsschlüssel eines Benutzers; Erstellung/Einsicht rechtegebunden. | `UserRightsConst.Administration.AccessTokens`, `AccessTokensController.cs` |
@@ -0,0 +1,101 @@
# Hypothesen
Sammlung aller Aussagen, die sich aus den Artefakten nicht eindeutig belegen ließen. Jede Hypothese nennt die betroffenen Anforderungen, die fehlende Information und den vorgeschlagenen Klärungsweg (Schritt 7 der RRE-Methodenkette: Validierung durch Fachexperten).
---
## H-01 – Semantik der Eskalations-Selektionskriterien
**Betroffene Anforderungen:** SyRS-039, SwRS-068
**Aussage [HYPOTHESE]:** Die Filterbedingungen `e.ObArt = 2` und `e.status < 2` in der Eskalations-SQL selektieren „offene ToDo-Objekte vom Typ Ticket"; `et.Status = 1` bedeutet „Eskalationstyp aktiv".
**Fehlende Information:** Die Wertebedeutung von `ObArt` und `status` ist im gelesenen Code nicht als Enum/Konstante dokumentiert; die Interpretation stützt sich nur auf Kontext (TDLKind, ToDoType-Cast in EscalationBL.cs:275).
**Klärungsweg:** Fachexperten-Review der Escalations-Tabelle bzw. Nachverfolgung der ToDoType-Enumeration.
## H-02 – Passworthashes ohne Salt
**Betroffene Anforderungen:** SwRS-022, SyRS-008
**Aussage [HYPOTHESE]:** Die SHA1-Passworthashes werden ohne benutzerindividuelles Salt gebildet; identische Passwörter erzeugen identische Hashwerte.
**Fehlende Information:** Die Implementierung von `SHA1Decoder.GetDecodedSHA1String` wurde nicht gelesen; ein internes statisches Salt/Pepper ist nicht ausgeschlossen.
**Klärungsweg:** Code-Review von SHA1Decoder (Centron.BL/Core/CryptoUtils.cs bzw. zugehörige Klasse) und Stichprobe zweier Konten mit gleichem Passwort in einer Testdatenbank.
## H-03 – Keine harte Festschreibung nach FIBU-Export (GoBD)
**Betroffene Anforderungen:** SyRS-031, SwRS-043, StRS-025
**Aussage [HYPOTHESE]:** Das System kennt keine harte Festschreibung („Unveränderbarkeit") exportierter oder gebuchter Rechnungen; die Warnung mit Bestätigungsmöglichkeit (HandleIsAlreadyExported) ist der einzige Schutzmechanismus. GoBD-konforme Unveränderbarkeit wird über die Versionshistorie, nicht über ein Änderungsverbot angestrebt.
**Fehlende Information:** Es wurde nicht die gesamte Codebasis auf weitere Sperrmechanismen (z. B. in BookKeepingExportBL, Perioden-/Abschlusslogik) durchsucht.
**Klärungsweg:** Fachexperteninterview zur GoBD-Strategie; gezielte Suche nach Periodensperren/Abschlussdatum-Prüfungen.
## H-04 – Keine Kassen-Fiskalisierung (TSE)
**Betroffene Anforderungen:** SyRS-064, StRS-032
**Aussage [HYPOTHESE]:** Das Kassenbuch/der Barverkauf besitzt keine Anbindung an eine technische Sicherheitseinrichtung (TSE) oder andere Fiskalisierungslösungen (Suchbegriffe „TSE", „Fiskal", „fiscal" ohne Treffer in den Kassen-BL-Dateien).
**Fehlende Information:** Vollständige Suche über alle Projekte (inkl. Reports/Gateway) steht aus; ggf. erfolgt Fiskalisierung außerhalb der analysierten Codebasis.
**Klärungsweg:** Befragung, ob Barverkauf im Produkteinsatz KassenSichV-relevant ist; ggf. bewusste Ausklammerung dokumentieren.
## H-05 – Bedeutung von HelpdeskStateBase.State
**Betroffene Anforderungen:** SwRS-066, SyRS-037
**Aussage [HYPOTHESE]:** Das int-Feld `State` an HelpdeskState kodiert eine Basiskategorie des Status (z. B. offen/geschlossen-artig), während der konkrete Abschlussstatus über die Einstellung `GetClosedHelpdeskState` bestimmt wird.
**Fehlende Information:** Wertebereich und Auswertungsstellen von `HelpdeskStateBase.State` wurden nicht erhoben.
**Klärungsweg:** Verwendungssuche von `.State` auf HelpdeskState-Objekten; Abgleich mit Einstellungsseite „Status".
## H-06 – WebCart-Bestellweg in die Belegkette
**Betroffene Anforderungen:** SyRS-067, StRS-021
**Aussage [HYPOTHESE]:** Eine WebCart-Bestellung erzeugt serverseitig einen Verkaufsbeleg (Auftrag oder Web-Beleg mit Überführung), der im WPF-Client weiterbearbeitet wird.
**Fehlende Information:** Der konkrete Erzeugungspfad (ReceiptCartBL → Belegart, Statuskette ReceiptCartState) wurde nicht analysiert.
**Klärungsweg:** Analyse von ReceiptCartBL/ReceiptCartReleaseSystemBL und ReceiptCartState (inkl. Freigabesystem).
## H-07 – Währungsbehandlung der Kreditlimitprüfung
**Betroffene Anforderungen:** SyRS-023, SwRS-038
**Aussage [HYPOTHESE]:** Die Kreditlimitprüfung rechnet implizit in Hauswährung (Anzeige mit `defaultCountry.CurrencySymbol`); Fremdwährungsbelege werden über CurrencyFactor einbezogen. Eine explizite Umrechnungsprüfung war im gelesenen Ausschnitt nicht sichtbar.
**Fehlende Information:** Implementierung von GetUsedLimitAmount je Belegart (Fremdwährungsumrechnung) nicht gelesen.
**Klärungsweg:** Review der GetUsedLimitAmount-Implementierungen in den SpecificLogic-Klassen.
## H-08 – Funktionsumfang des DSGVO-Moduls
**Betroffene Anforderungen:** SyRS-080, StRS-026
**Aussage [HYPOTHESE]:** Das DSGVO-Modul umfasst über die AV-Vertragsverwaltung hinaus weitere Funktionen (z. B. Auskunfts-/Löschprozesse), die hier nicht erhoben wurden.
**Fehlende Information:** Inhalt von Modules.Administration.DSGVO (WPF) wurde nicht gelesen.
**Klärungsweg:** UI-/Code-Sichtung des DSGVO-Moduls; Abgleich mit Datenschutz-Anforderungen des Zielsystems.
## H-09 – Führendes Kundendatenmodell (Kunden vs. Accounts)
**Betroffene Anforderungen:** StRS-001, SwRS-053
**Aussage [HYPOTHESE]:** Das modernere Accounts-Modell (Accounts/AccountCustomer, cvw_AccountSearchAcc) ist das strategisch führende Kundenmodell; die Legacy-Tabelle `Kunden` (Customer-Entität) bleibt aus Kompatibilität parallel bestehen und wird synchron gehalten (Indiz: AccountBL.ExistsAccountForOldCustomer, „IsAccountManagementActive"-Umschaltung).
**Fehlende Information:** Synchronisationsmechanik und Migrationsstand zwischen beiden Modellen wurden nicht analysiert.
**Klärungsweg:** Fachexperteninterview; Analyse von AccountBL/AdressstammReplacementBL.
## H-10 – Pausenzeit-Verrechnung in der Zeitdauer
**Betroffene Anforderungen:** SwRS-069, SyRS-040
**Aussage [HYPOTHESE]:** Die persistierte Dauer `Timer` enthält die Pause noch (Timer = Stop − Start); `LunchTime` wird erst bei Auswertung/Abrechnung abgezogen.
**Fehlende Information:** Abrechnungsseitige Verwendung von LunchTime nicht verfolgt.
**Klärungsweg:** Analyse der Abrechnungs-/Statistikpfade (TimerBilling, EmployeeHelpdeskTimerStatisticBL) auf LunchTime-Abzug.
## H-11 – Tiefe des Produktionsmoduls
**Betroffene Anforderungen:** SyRS-081, StRS-029
**Aussage [HYPOTHESE]:** Das Produktionsmodul deckt einfache Konfektionierung (Stücklisten, Statusverfolgung, Maschinenzuordnung) ab, ohne Kapazitäts-/Terminplanung oder Rückmeldewesen.
**Fehlende Information:** ProductionBL/ProductionOrderBL wurden nur oberflächlich gesichtet.
**Klärungsweg:** Detailanalyse der Produktions-BL in einer Folgeiteration.
## H-12 – Durchsetzungsort der Kontosperrfelder
**Betroffene Anforderungen:** SyRS-009
**Aussage [HYPOTHESE]:** Die Felder IsAccountDisabled/AccountDisabledFrom-/ToDate werden im Anmeldeprozess (Authenticator) ausgewertet und verhindern die Anmeldung im Sperrfenster.
**Fehlende Information:** Der Authenticator-Code (AuthenticatorFactory/BasicAuth-Pfad) wurde nicht gelesen.
**Klärungsweg:** Review der Authentifizierungs-Pipeline (Centron.WebServices.Core/Interception, AuthenticateAttribute).
## H-13 – Schweizer ESR-/QR-Zahlteil-Formatstand
**Betroffene Anforderungen:** SwRS-059
**Aussage [HYPOTHESE]:** Die ESR-Logik entspricht dem klassischen ESR-Verfahren; ob die aktuelle Schweizer QR-Rechnung unterstützt wird, ist unklar.
**Fehlende Information:** ReceiptEsrBL und Switzerland-Ordner wurden nicht im Detail gelesen.
**Klärungsweg:** Detailanalyse Switzerland-BL; fachliche Prüfung gegen SIX-Spezifikation.
## H-14 – Zuordnungsregeln des MailScanners
**Betroffene Anforderungen:** SyRS-074
**Aussage [HYPOTHESE]:** Der MailScanner ordnet eingehende Mails über Ticketnummer im Betreff bzw. Absenderadresse bestehenden Tickets zu und erzeugt sonst neue Tickets gemäß Postfachkonfiguration.
**Fehlende Information:** MailScannerBL wurde nicht gelesen (nur Existenz und Konfigurationsseiten belegt).
**Klärungsweg:** Codeanalyse MailScannerBL in Folgeiteration.
## H-15 – Konfliktverhalten der Exchange-Synchronisation
**Betroffene Anforderungen:** SyRS-075
**Aussage [HYPOTHESE]:** Die Kalender-Synchronisation ist bidirektional mit Konfliktauflösung zugunsten der zuletzt geänderten Quelle.
**Fehlende Information:** Synchronisationscode nicht analysiert; das dokumentierte „Bugprotokoll" (docs/features/exchange-sync-bugprotokoll.md) deutet auf komplexe Randfälle.
**Klärungsweg:** Analyse der Sync-BL und des Bugprotokolls; Fachexperteninterview.
## H-16 – Vollständigkeit der REST-API gegenüber dem RPC-Dienst
**Betroffene Anforderungen:** SyRS-003, SwRS-088
**Aussage [HYPOTHESE]:** Die REST-v1-API deckt nur eine Teilmenge der Fachfunktionen ab; der klassische ICentronRestService (29 Teilbereiche) ist der funktional vollständige Kanal, den WPF-Client und Altintegrationen nutzen.
**Fehlende Information:** Methodenzählung/Abgleich beider Kanäle wurde nicht durchgeführt.
**Klärungsweg:** Generierter Abgleich der Methodenlisten beider Schnittstellen (Basis für API-Zielbild der Neuimplementierung).
@@ -0,0 +1,717 @@
# StRS – Stakeholder Requirements Specification
**System:** NEXOWARE c-entron ERP-Suite (Reverse Requirements Engineering aus Codebasis)
**Norm-Bezug:** ISO/IEC/IEEE 29148:2018, Kap. 9.4 (StRS-Informationsgehalt)
**Erhebungsstand:** 2026-08-25, Commit 79c1142f48 (Branch main)
## 1. Zweck und Systemkontext
Die c-entron ERP-Suite ist ein Warenwirtschafts- und Servicemanagementsystem für IT-Systemhäuser und Managed-Service-Provider im deutschsprachigen Markt (Hersteller: NEXOWARE Systems GmbH, Produktname `NEXOWARE c-entron ERP` laut `Directory.Build.props`). Sie umfasst Verkaufs- und Einkaufsbelegwesen, Vertrags- und Ticketabrechnung, Helpdesk, Lager/Logistik, Finanzen (OPOS, Mahnwesen, SEPA, FIBU-Export, E-Rechnung), Webportale für Endkunden sowie zahlreiche Integrationen (EDI-Distributoren, RMM, Banken, Versanddienste, Telefonie).
**Identifizierte Akteure (aus Rechten, Modulen und UI abgeleitet):**
| Akteur | Ableitung |
|---|---|
| Vertriebsmitarbeiter (Innendienst/Außendienst) | Belegwesen, `SalesRepresentativeI3D`/`OfficeStaffI3D` in `ReceiptContract`; Provisionsmodule |
| Servicemitarbeiter / Techniker | Helpdesk-Rechte (`CentronRights.md`), ServiceBoard-Web-UI, Zeiterfassung |
| Lagermitarbeiter | Module Inventur, Kommissionierung, Artikelverwaltung (`ModuleRegistration.cs`) |
| Einkäufer | Bestellvorschlagsliste, EDI-Verwaltung, Lieferantenbelege (`UserRightsConst.Purchase`) |
| Buchhalter / Finanzverantwortlicher | Module Mahnung, OPOS, SEPA, Zahlungseingang, Buchhaltungsexport (`ModuleRegistration.cs` Region „Buchhaltung/Finanzen") |
| Controller / Geschäftsführung | Module Analytics, Management Info, Vertragsauswertung |
| Administrator | Rechteverwaltung, Mandanten, Mitarbeiter, Einstellungen, SQL-Manager |
| Endkunde (des Systemhauses) | WebAccount-Login, Kundenportal-/WebCart-/WebOffer-Routen in `CentronNexus` |
| Externe Anwendungen/Partner | `ApplicationKind.cs` (ca. 40 anmeldefähige Anwendungen, u. a. RMM-Konnektoren, DocBee, TANSS) |
**Hinweis zur Methodik:** Alle Anforderungen sind aus statischer Analyse der Codebasis abgeleitet. `Fakt` = belegte technische Beobachtung; `Aussage` = fachliche Interpretation. Anforderungen ohne PRIMÄR-Beleg in risikobehafteten Bereichen (Sicherheit, Abrechnung, Berechtigungen) sind als `[HYPOTHESE]` markiert.
---
## 2. Stakeholder-Anforderungen
```
ID: StRS-001
Titel: Einheitliche Kunden- und Adressverwaltung
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter, Servicemitarbeiter
Vorbedingung: Benutzer ist angemeldet und besitzt Kundenstamm-Rechte
Fakt: Es existieren zwei registrierte Adressmodule (AccountManagementAppModuleController und CrmAppModuleController), umgeschaltet über die Einstellung CrmSettings.IsAccountManagementActive; die Customer-Entität führt Zahlungskonditionen je Belegart, Kreditlimit, Preisliste, Bankverbindungen und Dokumentordner je Belegart.
Aussage: Das System soll einen zentralen Adress-/Kundenstamm bereitstellen, in dem alle kundenbezogenen Stammdaten (Ansprechpartner, Zahlungs-/Lieferkonditionen, Kreditlimit, Preisfindung, Bankdaten, Dokumente) gepflegt werden und der von allen Modulen (Belege, Tickets, Verträge) referenziert wird.
Ergebnis: Jeder Geschäftsvorgang (Beleg, Ticket, Vertrag) ist eindeutig einem Kunden zugeordnet; Konditionen werden automatisch aus dem Kundenstamm übernommen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs (PaymentCondition*I3D je Belegart, CreditLimit, PriceList, Bank*) – Begründung: Datenmodell erzwingt kundenbezogene Konditionen als Quelle der Belegerstellung.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:522-531 – Begründung: Registrierung Adressstamm/CRM inkl. Rechteprüfung UserRightsConst.Sales.Customer.CustomerCommon.ID belegt das Modul als zentralen Einstieg.
- [KONTEXT] README.md („create one in c-entron.NET Adressstamm") – Begründung: Bestätigt den Adressstamm als führendes Stammdatenmodul.
Prüfidee: Neuanlage eines Kunden mit abweichender Rechnungs-Zahlungskondition; anschließende Rechnungserstellung muss diese Kondition vorbelegen.
Tracelinks: SyRS-018, SyRS-022, SyRS-023, SyRS-066
Konsolidierung: Kandidat: Doppelstruktur Adressstamm vs. CRM-Modul (per Einstellung umgeschaltet) sowie Legacy-Tabelle Kunden vs. Accounts-Datenmodell – im Zielsystem zu einem Kundenstamm zusammenführen.
Status: belegt
```
```
ID: StRS-002
Titel: Durchgängige Verkaufsbelegkette
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter
Vorbedingung: Kunde ist angelegt; Benutzer besitzt Belegrechte
Fakt: Die Codebasis implementiert die Belegarten Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag als Ableitungen von ReceiptBase mit Weitergabe-Mechanik (Origin-Verweise) und Statusfortschreibung der Vorgängerbelege.
Aussage: Das System soll den Verkaufsprozess als durchgängige Belegkette unterstützen: Angebote können in Aufträge, Aufträge in Lieferscheine/Rechnungen und Lieferscheine in Rechnungen überführt werden, ohne Daten neu zu erfassen.
Ergebnis: Folgebelege übernehmen Positionen und Konditionen des Vorgängers; verarbeitete Mengen werden am Ursprungsbeleg fortgeschrieben.
Belege:
- [PRIMÄR] docs/reference/receipts/receipts-backend-architecture.md (Belegartentabelle AngKopf/AufKopf/LiefKopf/RechKopf/AbholKopf/GutKopf/VertragKopf) – Begründung: dokumentiert die vollständige Belegartenlandschaft mit Tabellenzuordnung; Verzeichnisstruktur src/backend/Centron.Entities/Entities/Sales/Receipts bestätigt sie im Code.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs (UpdateOrigin, AddOriginReceiptItemForQuantityProcessedUpdate) – Begründung: Verarbeitete Mengen werden am Ursprungsbeleg fortgeschrieben, was die Kettenlogik durchsetzt.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3686 (CheckIfItemQuantitiesHaveChangedAlthoughTheItemsHaveBeenForwarded) – Begründung: Änderungsverbot weitergegebener Mengen erzwingt Konsistenz der Kette.
Prüfidee: Auftrag mit 2 Positionen in Lieferschein überführen; Ursprungsauftrag muss die verarbeitete Menge ausweisen und eine Mengenreduktion unter die gelieferte Menge ablehnen.
Tracelinks: SyRS-018, SyRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-003
Titel: Rechnungsstellung mit Storno und Gutschrift
Ebene: StRS
Typ: funktional
Akteur: Buchhalter, Vertriebsmitarbeiter
Vorbedingung: Rechnung existiert
Fakt: ReceiptInvoiceBL.CancelInvoice erzwingt für Stornierungen ein eigenes Recht sowie fachliche Vorbedingungen (nicht bereits storniert, keine Barrechnung, nicht weiterverarbeitet, nicht exportiert, bei Vertragsrechnungen nur die letzte); Gutschriften existieren als eigene Belegart (GutKopf).
Aussage: Das System soll Rechnungen erzeugen, deren nachträgliche Korrektur nur kontrolliert erfolgt: per berechtigungspflichtigem Storno unter definierten Vorbedingungen oder per Gutschrift.
Ergebnis: Stornierte Rechnungen bleiben als neue, als „storniert" gekennzeichnete Version erhalten; die Buchhaltungsintegrität bleibt gewahrt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/ReceiptInvoiceBL.cs:143-206 (CancelInvoice) – Begründung: Codifizierte Vorbedingungen und Rechteprüfung RIGHT_RECHNUNGSTORNIEREN setzen die Regel durch.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs (Canceled=3, „storniert") – Begründung: Statusmodell enthält Storno als eigenen Zustand.
Prüfidee: Stornoversuch einer bereits an die FIBU exportierten Rechnung muss mit Fehlermeldung abgelehnt werden; Storno einer offenen Rechnung erzeugt neue Version mit Status „storniert".
Tracelinks: SyRS-027, SyRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-004
Titel: Wiederkehrende Vertragsabrechnung
Ebene: StRS
Typ: funktional
Akteur: Buchhalter, Vertriebsmitarbeiter, MSP-Betreiber
Vorbedingung: Vertrag mit Abrechnungsintervall und Positionen existiert
Fakt: ReceiptContract führt BillingIntervalKind/-Duration, AutomatedBilling, Kontingent- und Zählerfelder; AutomaticFacturaBL erzeugt Rechnungen aus Verträgen, protokolliert Abrechnungsläufe (StoreBillingResult/LoadBillingResult) und verarbeitet Zählerstände, Freimengen und Staffelpreise.
Aussage: Das System soll wiederkehrende Leistungen (Wartung, Miete, MSP-Services, Klick-/Zählerabrechnung) vertragsbasiert in konfigurierbaren Intervallen automatisch fakturieren, inklusive Kontingentverrechnung und nachvollziehbarem Abrechnungsprotokoll.
Ergebnis: Je Abrechnungslauf entstehen Rechnungen mit Vertragsbezug; Vertragszähler, Kontingente und „zuletzt abgerechnet"-Daten werden fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs (SearchBillingContracts, StoreInvoiceToContract, StoreBillingResult, GetCounterFreeCount, GetCounterScalePrices) – Begründung: implementiert Suche abrechenbarer Verträge, Rechnungszuordnung und Laufprotokoll.
- [PRIMÄR] docs/reference/receipts/contracts-backend.md (Billing Configuration, Automated Billing Process) – Begründung: dokumentiert Intervalle (Daily/Monthly/Quarterly/Yearly), AutomatedBilling-Flag und Ablauf; Felder in ReceiptContract.cs nachgewiesen.
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md – Begründung: beschreibt RMM-Artikel-Logik als Teil der Vertragsabrechnung.
Prüfidee: Vertrag mit Monatsintervall und Zählerposition anlegen; Abrechnungslauf simulieren und prüfen, dass Freimenge abgezogen, Staffelpreis angewendet und ein Abrechnungsergebnis-Datensatz geschrieben wird.
Tracelinks: SyRS-032, SyRS-033, SyRS-034, SyRS-035, SyRS-036
Konsolidierung: Kandidat: drei Abrechnungswege (Vertragsabrechnung, vereinfachte Ticketabrechnung, Pauschalabrechnung) mit überlappender Funktion – im Zielsystem als eine Abrechnungs-Engine konsolidierbar.
Status: belegt
```
```
ID: StRS-005
Titel: Ticketbasierter Kundenservice (Helpdesk)
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Support-Leitung, Endkunde
Vorbedingung: Benutzer besitzt Helpdesk-Rechte bzw. Endkunde hat Portalzugang
Fakt: Das Helpdesk-Modul umfasst Tickets (hlpdsk_requests) mit konfigurierbaren Status, Prioritäten, Kategorien (Haupt-/Unterkategorien), Typen, Fälligkeit, Bearbeitern, Historie, Verknüpfung zu Geräten, Verträgen und Belegen; Rechte differenzieren Sehen/Anlegen/Bearbeiten/Schließen inkl. „nur eigene"/„nur eigene Filiale".
Aussage: Das System soll Servicefälle als Tickets führen, mit konfigurierbarem Statusmodell, Priorisierung, Kategorisierung, Zuständigkeiten, Fälligkeiten und vollständiger Historie, und den Zugriff feingranular nach Rolle, Besitz und Filiale steuern.
Ergebnis: Servicefälle sind lückenlos dokumentiert und über Listen (Ticket-Liste, ServiceBoard, Kanban) bearbeitbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs und HelpdeskState/Priority/Category/Type-Entitäten – Begründung: Datenmodell der Ticketverwaltung mit konfigurierbaren Steuerungsobjekten.
- [PRIMÄR] src/webservice/.../Rights/UserRightsConst.cs:1952-2016 (Klasse Helpdesk mit SHOW_HELPDESK, SHOW_HELPDESK_ONLY_OWN, SHOW_HELPDESK_ONLY_OWN_BRANCH, CLOSE_REQUEST u. a.) – Begründung: Rechtekonstanten erzwingen die abgestufte Zugriffssteuerung.
- [SEKUNDÄR] CentronRights.md Abschnitt „Helpdesk" – Begründung: dokumentiert die fachliche Bedeutung jedes Helpdesk-Rechts.
Prüfidee: Benutzer mit SHOW_HELPDESK_ONLY_OWN darf nur Tickets sehen, in denen er Bearbeiter oder Verantwortlicher ist (Listen- und Detailzugriff testen).
Tracelinks: SyRS-037, SyRS-038, SyRS-039, SyRS-069
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Leistungserfassung und Ticketabrechnung
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Buchhalter
Vorbedingung: Ticket existiert; Mitarbeiter hat Zeiterfassungsrechte
Fakt: HelpdeskTimer erfasst Start/Stopp/Pause, Zeittyp, Abrechenbarkeit (Calculable), Abrechnungsstatus (BillingStateI3D), Vertragskontext, Kundensignatur (IsSigned) und Referenzen auf Auftrag/Lieferschein/Rechnung; TimerBillingBL und CreateReceiptForHelpdeskTimers erzeugen Belege aus Zeiten; Zuschläge über HourlySurchargeRates.
Aussage: Das System soll auf Tickets erfasste Arbeitszeiten (inkl. Anfahrten, Zuschlägen, Pausen, Kundensignatur) verwalten und diese gesammelt in Rechnungen oder Lieferscheine überführen, wobei der Abrechnungsstatus jeder Zeit nachvollziehbar bleibt.
Ergebnis: Abgerechnete Zeiten sind mit Belegpositionen verknüpft und gegen unberechtigte Änderung geschützt.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskTimerArea/HelpdeskTimer.cs (Calculable, BillingStateI3D, IsSigned, OrderAssetItemI3D/DeliveryListAssetItemI3D/InvoiceAssetItemI3D) – Begründung: Datenmodell verankert Abrechnungszustand und Belegverknüpfung je Zeit.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/TimerBilling/TimerBillingBL.cs (SearchTimers, SaveTimer mit ThrowIfUserDoesntHaveRightToChangeHelpdeskTimers, UpdateOrderItems) – Begründung: Abrechnungsmodul mit Rechteprüfung implementiert den Prozess.
- [SEKUNDÄR] CentronRights.md („Zeiten bearbeiten", „nur eigene Zeiten", „Unterschrift aus Zeit löschen", „Helpdeskzeiten verschieben… nur wenn nicht Teil eines Belegs") – Begründung: beschreibt die fachlichen Einschränkungen der Zeitbearbeitung.
Prüfidee: Zeit mit Signatur erfassen, in Rechnung abrechnen; anschließender Verschiebe-/Löschversuch der Zeit muss abgelehnt werden, Signaturlöschung nur mit Spezialrecht möglich sein.
Tracelinks: SyRS-040, SyRS-041, SyRS-042
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Eskalation von Servicefällen
Ebene: StRS
Typ: funktional
Akteur: Support-Leitung, Servicemitarbeiter
Vorbedingung: Eskalationstypen sind konfiguriert und aktiv
Fakt: EscalationBL implementiert bis zu drei Eskalationsstufen mit Wartezeiten (Stunden1-3), Arbeitszeitfenster (WorkTimeFrom/To), Samstag-/Sonntagsschaltern und Mailversand über Vorlagen; Läufe werden protokolliert (EscalationsLog).
Aussage: Das System soll überfällige Vorgänge automatisch und mehrstufig eskalieren, dabei Arbeitszeiten und Wochenenden berücksichtigen und jede Eskalation protokollieren, damit Service-Zusagen überwacht werden können.
Ergebnis: Verantwortliche werden stufenweise benachrichtigt; Eskalationshistorie ist auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/Escalation/EscalationBL.cs:223-345 (DoEscalation, ShouldEscalated, SetNextEscDay) – Begründung: implementiert Stufenlogik, Zeitfenster und Wochenendregeln.
- [PRIMÄR] EscalationBL.cs:937-994 (WriteLOG, GetEscalationsLog) – Begründung: Protokollierung der Eskalationsläufe ist codiert.
Prüfidee: Eskalationstyp mit Stufe 1 = 4 h Wartezeit und Arbeitszeit 8–17 Uhr konfigurieren; Testlauf (TestEscalation) muss außerhalb des Zeitfensters keine, innerhalb eine Stufe-1-Eskalation liefern.
Tracelinks: SyRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Einkaufsabwicklung mit Lieferantenbelegen
Ebene: StRS
Typ: funktional
Akteur: Einkäufer, Buchhalter
Vorbedingung: Lieferant ist angelegt
Fakt: Nummernkreise und Entitäten existieren für Anfrage (AnfrKopf), Bestellung (BestKopf2), Wareneingang (WareKopf), Lieferantenrechnung/Kalkulation (KalkKopf), Lieferantengutschrift (LiGutKopf); BL-Ordner SupplierOrders/SupplierDeliveryLists/SupplierInvoices/SupplierCreditVouchers; Rechteklassen Purchase.Supplier.Offer/Order/DeliveryList/Invoice/CreditVoucher/Contract.
Aussage: Das System soll den Einkaufsprozess mit eigener Belegkette (Anfrage, Bestellung, Wareneingang, Lieferantenrechnung, Lieferantengutschrift) und lieferantenbezogenen Rechten unterstützen.
Ergebnis: Einkaufsvorgänge sind je Lieferant dokumentiert; Wareneingänge aktualisieren Bestände und Kalkulationen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:40-55 (Inquiry→AnfrKopf, PurchaseOrder→BestKopf2, Intake→WareKopf, VendorInvoice→KalkKopf, SupplierCreditVoucher→LiGutKopf) – Begründung: Nummernkreis-Tabellenzuordnung weist die Einkaufsbelegarten nach.
- [PRIMÄR] src/webservice/.../UserRightsConst.cs:1801-1845 (Purchase.Supplier.* Rechteklassen) – Begründung: Rechtekonstanten je Einkaufsbelegart belegen die geforderte Zugriffssteuerung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/SupplierOrders u. a. Ordner – Begründung: eigenständige Geschäftslogik je Lieferantenbelegart existiert.
Prüfidee: Bestellung anlegen, Wareneingang buchen; Bestand und Bestellstatus müssen fortgeschrieben werden (Intake-Update in SaveReceipt-Pipeline).
Tracelinks: SyRS-046, SyRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Bestellvorschläge und Distributorenpreisvergleich
Ebene: StRS
Typ: funktional
Akteur: Einkäufer
Vorbedingung: Artikelstamm und Distributorendaten vorhanden
Fakt: OrderSuggestionList-BL liefert Vorschläge nach Artikel, Auftrag und Lager, Distributorenlisten und eine Preismatrix je EAN/Herstellercode; ITscope- und Icecat-API-Projekte existieren unter src/apis.
Aussage: Das System soll Bestellvorschläge aus Bedarfen (Aufträge, Mindestbestände) erzeugen und Preise/Verfügbarkeiten mehrerer Distributoren vergleichbar machen, um die Beschaffung wirtschaftlich zu steuern.
Ergebnis: Einkäufer erhalten priorisierte Bestellvorschläge mit Bezugsquellenvergleich.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Purchasing/OrderSuggestionList/*.cs (GetOrderSuggestionArticle/Order/WH, GetDistributors, GetPriceMatrixFromDB) – Begründung: implementiert Vorschlags- und Vergleichslogik.
- [PRIMÄR] src/apis/Centron.APIs.ITscopeDataAccess, src/apis/Centron.APIs.IcecatDataAccess – Begründung: Anbindung externer Produkt-/Preisdatenquellen ist als eigene Projekte nachgewiesen.
Prüfidee: Artikel mit Unterschreitung des Mindestbestands anlegen; Bestellvorschlagsliste muss den Artikel mit Distributorenpreisen anzeigen.
Tracelinks: SyRS-047, SyRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-010
Titel: Lagerführung mit Seriennummernverfolgung
Ebene: StRS
Typ: funktional
Akteur: Lagermitarbeiter, Servicemitarbeiter
Vorbedingung: Artikel und Läger sind angelegt
Fakt: Bestände werden je Artikel und Lager geführt (ArticleStock/SecondaryStock); Belege buchen Bestände automatisch (BookArticles/UnBookArticles); Seriennummern (BarCode) haben einen Lebenszyklusstatus über 28 Zustände und Verweise auf Auftrags-/Liefer-/Rechnungs-/Gerätepositionen.
Aussage: Das System soll Lagerbestände artikel- und lagergenau führen, Belegbewegungen automatisch buchen und serialisierte Artikel über ihren gesamten Lebenszyklus (Wareneingang bis Verkauf/RMA/Verschrottung) einzeln verfolgen.
Ergebnis: Bestände und Seriennummernstatus sind jederzeit konsistent zur Belegkette.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs (UpdateStock; IncrementsStock je Belegart) – Begründung: automatische Bestandsbuchung bei Belegspeicherung ist codiert.
- [PRIMÄR] src/backend/Centron.Interfaces/Warehousing/BarcodeState.cs (28 Statuswerte) und src/backend/Centron.Entities/Entities/Warehousing/BarCode.cs (AufPosI3D, LiefPosI3D, RechPosI3D…) – Begründung: Seriennummern-Lebenszyklus und Belegverweise sind im Datenmodell verankert.
Prüfidee: Serialisierten Artikel per Lieferschein ausbuchen; BarCode.State muss auf InDeliveryList/AssignedToDeliveryList wechseln und der Lagerbestand sinken.
Tracelinks: SyRS-050, SyRS-051, SyRS-052
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Inventur
Ebene: StRS
Typ: funktional
Akteur: Lagermitarbeiter
Vorbedingung: Recht Purchase.Inventory; Läger vorhanden
Fakt: InventoryBL implementiert Inventuren mit/ohne Seriennummern, Inventurgruppen, Lagerabschluss (CloseStorages), Zählmengenerfassung (AddArticle) und Verlust-Kennzeichnung von Seriennummern (VerlustInventurI3D, BarcodeState.LostAtStocktaking).
Aussage: Das System soll Inventuren je Lager unterstützen: Zählmengen erfassen, Läger für die Zählung abschließen, Differenzen (inkl. verlorener Seriennummern) dokumentieren.
Ergebnis: Nach Inventurabschluss sind Bestände korrigiert und Verluste nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/InventoryManagement/InventoryBL.cs (AddInventory, CreateInventoryGroup, CloseStorages, IsStockClosed) – Begründung: Inventurprozess vollständig implementiert.
- [PRIMÄR] src/backend/Centron.Interfaces/Warehousing/BarcodeState.cs (LostAtStocktaking=10) – Begründung: Verlustzustand für Seriennummern existiert im Statusmodell.
Prüfidee: Inventur ohne Seriennummern anlegen, Lager abschließen; weitere Zählungen auf dem geschlossenen Lager müssen abgelehnt werden.
Tracelinks: SyRS-053
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Kommissionierung und Versand
Ebene: StRS
Typ: funktional
Akteur: Lagermitarbeiter
Vorbedingung: Auftrag mit lieferbaren Positionen existiert
Fakt: Kommissionierungsmodul (OrderCommission) mit PartialCommissionOrderState; Versandanbindungen GLS und Shipcloud als API-Projekte mit Einstellungsseiten und Pakettemplates (ShipcloudPackageTemplate); SaveReceipt aktualisiert referenzierte Kommissionieraufträge.
Aussage: Das System soll die Kommissionierung von Aufträgen (auch in Teilaufträgen) unterstützen und Versandaufträge inklusive Paketdaten an Versanddienstleister (GLS, Shipcloud) übergeben.
Ergebnis: Gelieferte Mengen und Kommissionierstatus werden fortgeschrieben; Versandlabels können erzeugt werden.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Warehousing/Commissions/PartialCommissionOrderState.cs und ReceiptBL.cs:3849 (UpdatePartialCommissionOrderFromReceipt) – Begründung: Statusmodell und Fortschreibung aus Belegen sind codiert.
- [PRIMÄR] src/apis/Centron.Api.Gls, src/apis/Centron.Api.Shipcloud; src/backend/.../ShipcloudPackageTemplateBL.cs – Begründung: Versand-APIs und Paketvorlagen sind implementiert.
- [SEKUNDÄR] ModuleRegistration.cs (GlsSettingController, ShipcloudSettingController, OrderCommissionAppModuleController mit Recht Logistic.Commissioning) – Begründung: UI-Module und Rechte bestätigen den Prozessumfang.
Prüfidee: Teilkommissionierung eines Auftrags durchführen; Lieferschein-Erstellung muss die kommissionierte Menge übernehmen und den Kommissionierauftragsstatus aktualisieren.
Tracelinks: SyRS-054, SyRS-055
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Offene Posten und Mahnwesen
Ebene: StRS
Typ: funktional
Akteur: Buchhalter
Vorbedingung: Rechnungen mit Zahlungszielen existieren
Fakt: OposBL/OposRunBL und DunningBL/DunningRunBL implementieren OPOS-Listen und Mahnläufe mit drei Mahnstufen, kundenspezifischem Zustellweg (DunningSendType), abweichender Mahnadresse, befristbarem Mahnstopp je Kunde oder Beleg und Mailtext-Variablen.
Aussage: Das System soll offene Posten überwachen und ein mehrstufiges Mahnwesen (3 Stufen) bereitstellen, mit kundenindividuellen Zustellwegen, Mahnstopps (befristbar, je Kunde oder Einzelbeleg) und vorlagenbasierten Mahnschreiben.
Ergebnis: Überfällige Forderungen werden systematisch angemahnt; Ausnahmen sind dokumentiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs (GetDunningStopActive mit Begin/End, UpdateDunningStopAndInfo, UpdateDunningSettingsForCustomer, ThrowIfUserHasInsufficentRights) – Begründung: Mahnstopp-, Einstellungs- und Rechtelogik sind codiert.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs (None, Level1-3) – Begründung: dreistufiges Mahnstufenmodell.
Prüfidee: Kunde mit aktivem, befristetem Mahnstopp: Mahnlauf innerhalb des Zeitraums darf keine Mahnung erzeugen, danach schon.
Tracelinks: SyRS-056, SyRS-057
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: Zahlungsverkehr und Bankabgleich
Ebene: StRS
Typ: funktional
Akteur: Buchhalter
Vorbedingung: Bankverbindungen/Mandate gepflegt
Fakt: Module SEPA (PaymentTransaction), Zahlungseingang (Payments), Online-Banking mit FinAPI-Anbindung (Kontoumsätze laden, automatisch zuordnen, Beträge auf Belege buchen, Buchung rückgängig machen, Inspector-Prüfungen); Zahlungskonditionen kennen Lastschrift (DTADebit) und SEPA-Mandatspflicht (CheckIfMandatIsNeeded).
Aussage: Das System soll den Zahlungsverkehr unterstützen: SEPA-Lastschriften/-Überweisungen auf Basis von Mandaten, manuelle Zahlungseingangserfassung sowie automatischen Abgleich importierter Bankumsätze mit offenen Posten.
Ergebnis: Zahlungen werden Belegen zugeordnet; Zahlungsstatus (PaidFC) und OPOS werden fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Finances/OnlineBanking/OnlineBankingAccountTransactionsBL.cs (AutoCompleteAccountTransacitons, BookAmountsForAccountTransacitons, UndoBookingForAccountTransaciton) – Begründung: Bankabgleich mit Auto-Zuordnung und Buchung ist implementiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3744 (CheckIfMandatIsNeeded – „Abhängig: Zahlungskondition, Mandat") – Begründung: Mandatspflicht wird beim Belegspeichern durchgesetzt.
- [SEKUNDÄR] ModuleRegistration.cs:617-624 (SEPA- und Zahlungseingangs-Module mit Recht INCOMING_PAYMENT_TRANSACTIONS) – Begründung: Modulzuschnitt und Berechtigungen.
Prüfidee: Bankumsatz mit Verwendungszweck = Rechnungsnummer importieren; Auto-Zuordnung muss die Rechnung vorschlagen und Buchung den offenen Posten ausgleichen.
Tracelinks: SyRS-058, SyRS-059, SyRS-060
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Buchhaltungsübergabe und E-Rechnung
Ebene: StRS
Typ: funktional, Schnittstelle
Akteur: Buchhalter, Endkunde (Rechnungsempfänger), Behörden (XRechnung)
Vorbedingung: Abrechnungsdaten vorhanden
Fakt: BookKeepingExport/-Import inkl. DATEV-Belegtransfer-Modul; InvoiceZugferdBL erzeugt ZUGFeRD 1.0/2.0/2.1 bzw. XRechnung bis 3.0.1; ZugferdImportController für eingehende E-Rechnungen; ebInterface-API-Projekt (Österreich) vorhanden.
Aussage: Das System soll Rechnungsdaten an Finanzbuchhaltungen exportieren (u. a. DATEV) und elektronische Rechnungen in den normierten Formaten ZUGFeRD/XRechnung erzeugen und importieren können.
Ergebnis: Formatkonforme E-Rechnungen und FIBU-Übergaben ohne manuelle Doppelerfassung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs (+ .Zugferd10.cs, XInvoiceVersion3.cs) – Begründung: Formatimplementierung im Code.
- [PRIMÄR] src/webservice/Centron.Controllers/Controllers/.../ZugferdImportController.cs – Begründung: Import-Endpunkt existiert.
- [SEKUNDÄR] docs/reference/zugferd-field-mapping.md (Versionsliste, Feldzuordnung) – Begründung: dokumentiert unterstützte Versionen und Feld-Mapping.
- [SEKUNDÄR] ModuleRegistration.cs:589-599 (Buchhaltungsexport/-import, Datev Belegtransfer mit Rechten DataExchange.BOOKKEEPING_EXPORT/IMPORT) – Begründung: Module und Rechte.
Prüfidee: Rechnung als XRechnung 3.0.1 exportieren und mit KOSIT-Validator prüfen (Validator-Referenz in docs/guides/development/xrechnung.md).
Tracelinks: SyRS-061, SyRS-062, SyRS-063
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Provisionsabrechnung für den Vertrieb
Ebene: StRS
Typ: funktional
Akteur: Vertriebsleitung, Buchhalter
Vorbedingung: Provisionsschemata definiert
Fakt: Entitäten ReceiptProvisionSchema, -SchemaItem, -SchemaCustomerAssignment, -EmployeeGoal, -EmployeeLevel; Module Provisionsauswertung, Provisionsschemas verwalten, Kundenzuordnung mit getrennten Rechten und Lizenzen.
Aussage: Das System soll Vertriebsprovisionen regelbasiert ermitteln: Schemata mit Positionen, Kundenzuordnungen, Mitarbeiterzielen und -stufen sowie eine Auswertung je Mitarbeiter.
Ergebnis: Nachvollziehbare Provisionsberechnung auf Basis von Belegumsätzen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvisionSchema*.cs, ReceiptProvisionEmployeeGoal.cs, ReceiptProvisionEmployeeLevel.cs – Begründung: vollständiges Datenmodell der Provisionslogik.
- [PRIMÄR] ModuleRegistration.cs:426-438 (drei Provisionsmodule mit Rechten PROVISION_EVALUATION_MODULE, PROVISION_SCHEMA_MANAGEMENT, PROVISION_SCHEMA_CUSTOMER_ASSIGNMENT) – Begründung: Modul- und Rechtezuschnitt.
Prüfidee: Schema mit Kundenzuordnung anlegen, Beleg fakturieren, Provisionsauswertung muss den Umsatz dem zugeordneten Mitarbeiter zurechnen.
Tracelinks: SyRS-065
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: Rollenbasierte Zugriffssteuerung mit Besitz- und Filialbezug
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, alle Benutzer
Vorbedingung: Benutzer und Gruppen sind angelegt
Fakt: Ca. 750 Rechte-IDs (UserRightsConst) werden Benutzern über Gruppen (AppGroup) zugeordnet; Rechteprüfung erfolgt in UI (Modulregistrierung), BL (AppRightsBL.CheckRightsFromUser) und REST-API (Authorize-Attribute); es existieren einschränkende Rechte („nur eigene", „nur eigene Filiale") und eine Administratorengruppe (ADMIN_ACCOUNT = "Administratoren").
Aussage: Das System soll den Funktions- und Datenzugriff über ein zentral gepflegtes Rechtesystem steuern, das Rechte in Gruppen bündelt, sowohl gewährende als auch einschränkende Rechte (Besitz-/Filialbezug) kennt und auf allen Ebenen (UI, Geschäftslogik, API) durchgesetzt wird.
Ergebnis: Benutzer sehen und bearbeiten ausschließlich die ihren Rechten entsprechenden Module, Funktionen und Datenmengen.
Belege:
- [PRIMÄR] src/webservice/.../Rights/UserRightsConst.cs (750 Konstanten, Hierarchie nach Fachgebieten) – Begründung: vollständiger Rechtekatalog im Code.
- [PRIMÄR] docs/guides/development/check-userrights.md mit AppRightsBL.CheckRightsFromUser-Beispiel aus AccountBL.cs – Begründung: dokumentiertes, im Code verwendetes BL-Prüfmuster.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (Rechteprüfung je Modul) – Begründung: UI-Durchsetzung.
- [SEKUNDÄR] CentronRights.md – Begründung: fachliche Beschreibung inkl. Konzept „restricting right".
Prüfidee: Benutzer ohne CREATE_CUSTOMER erhält beim Anlegen eines Kunden die Fehlermeldung „Fehlende Rechte…" (BL-seitig, auch bei API-Aufruf).
Tracelinks: SyRS-006, SyRS-003
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Lizenzbasierte Modul- und Funktionsfreischaltung
Ebene: StRS
Typ: nicht-funktional (Produktstrategie), Sicherheit
Akteur: Hersteller (NEXOWARE), Administrator
Vorbedingung: Lizenzdatei/-server verfügbar
Fakt: Jedes WPF-Modul wird nur registriert, wenn eine Lizenz-GUID vorliegt (LicenseManager.HasLicense); Anwendungs-Logins validieren count/valid-until/version; der WebService verweigert den Start ohne gültige Lizenz vor dem DB-Verbindungsaufbau.
Aussage: Das System soll sämtliche Module und anmeldefähigen Anwendungen über Lizenzen (GUID, Anzahl, Ablaufdatum, Versionsgrenze) freischalten, sodass der Funktionsumfang je Kunde vertragsgemäß steuerbar ist.
Ergebnis: Nicht lizenzierte Funktionen sind unsichtbar bzw. nicht anmeldefähig.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs:102-105 (TryLoadLicense vor SetupDatabaseConnection, mit Kommentar) – Begründung: Startabbruch ohne Lizenz ist codiert.
- [PRIMÄR] ModuleRegistration.cs (durchgängig LicenseManager.Instance.HasLicense je Modul) – Begründung: Lizenz-Gate je Modul.
- [SEKUNDÄR] docs/reference/security/licensing-system.md – Begründung: dokumentiert Lizenzmodell (GUID, count, valid until date/version).
Prüfidee: Ohne PasswordManager-Lizenz dürfen die Passwort-Manager-Module nicht in der Modulliste erscheinen.
Tracelinks: SyRS-005, SyRS-011
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-019
Titel: Mandanten- und Filialorganisation
Ebene: StRS
Typ: funktional
Akteur: Administrator, Geschäftsführung
Vorbedingung: Lizenz für Mandanten-/Filialfunktion
Fakt: Mandator- und Branch-Entitäten (Branch.MandatorI3D, BookKeepingNumber, eigene Adresse); Nummernkreise optional je Filiale; Belege tragen BranchI3D und BranchOrigin (Ersteller/Betreuer); zahlreiche Rechte mit „nur eigene Filiale"; ZUGFeRD-Verkäuferdaten stammen aus Branch oder Mandator.
Aussage: Das System soll mehrere Mandanten mit untergeordneten Filialen abbilden; Belege werden einer Filiale zugeordnet (Regelherkunft: Ersteller oder Vertriebsbetreuer), Nummernkreise und Absenderdaten können je Filiale abweichen, und der Datenzugriff kann auf die eigene Filiale beschränkt werden.
Ergebnis: Organisationseinheiten arbeiten getrennt, aber im selben System; Auswertungen sind je Filiale/Mandant möglich.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/BranchArea/Branch.cs (MandatorI3D, BookKeepingNumber) – Begründung: Organisationsmodell im Datenmodell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7265-7284 (UpdateReceiptNumber mit branch-spezifischem NumberGroup) und :7309-7340 (GetBranchForNewReceipt nach BranchOrigin) – Begründung: filialabhängige Nummernvergabe und Filialermittlung sind codiert.
- [SEKUNDÄR] CentronRights.md (mehrere „nur eigene Filiale"-Rechte) – Begründung: fachliche Filialbeschränkungen.
Prüfidee: Zwei Filialen mit getrennten Rechnungsnummernkreisen konfigurieren; Rechnungen beider Filialen müssen aus dem jeweils richtigen Kreis nummeriert werden.
Tracelinks: SyRS-013, SyRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Kundenportal für Endkunden
Ebene: StRS
Typ: funktional
Akteur: Endkunde, Servicemitarbeiter
Vorbedingung: Endkunde besitzt WebAccount
Fakt: Nexus-Routen /customerportal/... bieten Tickets (Anlage über Formulare/Patterns, Details, Historie, Zeiten, Dokumente), Belege (Liste, Details, PDF-Vorschau, Verträge) und Dokumente; Authentifizierung über eigenen Auth-Pfad /auth/customer; Verwaltung der WebAccounts im Modul management/webaccounts.
Aussage: Das System soll Endkunden ein Webportal bieten, in dem sie eigene Tickets erstellen und verfolgen, eigene Belege (inkl. Verträge) einsehen und Dokumente abrufen können, getrennt vom internen Benutzerkreis.
Ergebnis: Endkunden-Self-Service reduziert interne Aufwände; Datenzugriff ist auf den jeweiligen Kunden beschränkt.
Belege:
- [PRIMÄR] src/nexus/CentronNexus Routen (@page "/customerportal/tickets/...", "/customerportal/receipts/...", "/customerportal/documents", "/auth/customer") – Begründung: implementierte Portalfunktionen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs – Begründung: eigener Kontotyp für Endkunden.
- [SEKUNDÄR] ModuleRegistration.cs (HelpdeskCustomerAccessSettingsController) – Begründung: Einstellungen für Kundenzugriff auf Helpdesk.
Prüfidee: WebAccount-Login darf nur Tickets/Belege des eigenen Kunden listen (Zugriff auf fremde ticketId per URL muss verweigert werden).
Tracelinks: SyRS-066, SyRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-021
Titel: Web-Shop für Endkunden (WebCart)
Ebene: StRS
Typ: funktional
Akteur: Endkunde, Vertriebsmitarbeiter
Vorbedingung: WebAccount mit Sonderpreisen existiert; WebCart-Lizenz
Fakt: Nexus-Routen /webcart (Shop, Warenkorb, Belege inkl. Verträge, Admin); README beschreibt: Sortiment stammt aus den „Sonderpreisen" des Kunden; ApplicationKind.WebCart mit eigener Lizenz und Ablauf aus Einstellungen.
Aussage: Das System soll Endkunden einen Web-Shop bieten, dessen Sortiment und Preise aus den kundenindividuellen Sonderpreisen stammen, mit Warenkorb und Bestellauslösung in die Belegkette des Systemhauses.
Ergebnis: Endkundenbestellungen entstehen ohne Medienbruch als Belege im ERP.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/WebCart (Routen /webcart/shop, /webcart/cart/..., /webcart/receipts/...) – Begründung: Shop-Funktionalität implementiert.
- [KONTEXT] README.md Abschnitt „WebCart" („available articles come from the customers ‚Sonderpreise'") – Begründung: dokumentiert die Sortimentsregel; Herkunft der Preise ist im Code (CustomerSpecialArticleBL) plausibilisiert, Detailregel dort nicht einzeln verifiziert.
Prüfidee: WebAccount ohne Sonderpreise sieht leeren Shop; nach Anlage eines Sonderpreises erscheint der Artikel im Shop.
Tracelinks: SyRS-067
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Digitale Angebotsannahme mit Signatur (WebOffer/C-Sign)
Ebene: StRS
Typ: funktional
Akteur: Endkunde, Vertriebsmitarbeiter
Vorbedingung: Angebot wurde als WebOffer bereitgestellt (Token-Link)
Fakt: WebReceiptState kennt SendToCustomer, FirstLoaded, AcceptFullWebReceipt, AcceptWebReceiptWithChangeRequests, Rejected, WebOfferSign, WebOfferSignedWithoutSignature, WebReceiptShutDown; Nexus-Seiten /weboffer/{Token} mit PDF-Vorschau und Signatur-Pad (DocumentSigning/IsolatedSignaturePad.razor); Commit „Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)".
Aussage: Das System soll Angebote per geschütztem Link an Endkunden ausliefern, deren Reaktion (vollständige Annahme, Annahme mit Änderungswünschen, Ablehnung) erfassen und eine digitale Unterschrift des Kunden aufnehmen; der Bearbeitungsstand ist für den Vertrieb sichtbar.
Ergebnis: Angebotsannahme ist ohne Papier dokumentiert; der Angebotsstatus spiegelt die Kundenreaktion.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs – Begründung: Statusmodell der Web-Angebotsannahme inkl. Signaturzustände.
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/*, DocumentSigning/IsolatedSignaturePad.razor, Route /weboffer/{Token} und /shareddocuments/{Token}/sign – Begründung: implementierte Kunden-UI inkl. Signatur.
- [KONTEXT] Git-Commit 89ccfd650d „C-Sign (WebOffer & Acceptance)" – Begründung: bestätigt Feature-Zuschnitt und Namen.
Prüfidee: Angebot als WebOffer versenden, im Browser annehmen und signieren; Status muss auf WebOfferSign wechseln und die Signatur am Vorgang gespeichert sein.
Tracelinks: SyRS-068
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: Objektbezogene Dokumentenverwaltung
Ebene: StRS
Typ: funktional
Akteur: alle internen Benutzer
Vorbedingung: Objekt (Kunde, Beleg, Ticket) existiert
Fakt: Kunden führen Ordnerverweise je Belegart (RootDir, OrderDir, InvoiceDir, HelpdeskDir …); ReceiptBL.EnsureReceiptDirectoryExists erzeugt beim Speichern automatisch einen Ordner „<Belegart> <Nummer>" unterhalb des passenden Elternordners; Directory-Provider existieren für Helpdesk/Checklisten; DocSync-Modul für Dokumentsynchronisation.
Aussage: Das System soll zu jedem Geschäftsobjekt (Kunde, Beleg, Ticket) automatisch eine strukturierte Dokumentenablage bereitstellen, in der zugehörige Dateien (Belege-PDF, Mails, Anhänge) auffindbar sind.
Ergebnis: Dokumente sind über die Objektakte auffindbar; Ordner entstehen ohne manuelles Zutun.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:9765-9803 (EnsureReceiptDirectoryExists) – Begründung: automatische Ordnererzeugung je Beleg ist codiert.
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs:52-66 (Directory-Verweise je Belegart) – Begründung: kundenbezogene Ablagestruktur im Datenmodell.
Prüfidee: Neuen Auftrag speichern; im Kunden-Auftragsordner muss ein Unterordner „Auftrag <Nummer>" entstehen und am Beleg (DirectoryI3D) verknüpft sein.
Tracelinks: SyRS-071
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Auswertungen und Reporting
Ebene: StRS
Typ: funktional
Akteur: Controller, Geschäftsführung, Vertriebsleitung
Vorbedingung: entsprechende Rechte/Lizenzen
Fakt: Module Analytics (SaleStatistics), Management Info, Vertragsauswertung, Leistungsnachweise, Mitarbeiterauslastung, MSP-Dashboard; ReportEngine mit Reportverwaltung und Reportserver (zeitgesteuerte Berichte); Excel-/PDF-Export in ReceiptBL.
Aussage: Das System soll betriebswirtschaftliche Auswertungen (Umsatz-, Vertrags-, Mitarbeiter-, MSP-Kennzahlen) sowie konfigurierbare Berichte mit zeitgesteuerter Erzeugung bereitstellen.
Ergebnis: Entscheidungsrelevante Kennzahlen sind rechtegeschützt abrufbar.
Belege:
- [PRIMÄR] ModuleRegistration.cs Region „Controlling/Analytics" und :579-581 (ReportServerAppModuleController), :868-870 (ReportEngineAppModuleController) – Begründung: Module inkl. Rechten (z. B. Controlling.Analytics.ID, Administration.REPORTSERVER).
- [PRIMÄR] src/backend/Centron.BL/ReportEngine, src/backend/Centron.BL/Statistics – Begründung: Auswertungs-Geschäftslogik vorhanden.
Prüfidee: Benutzer ohne Controlling-Rechte darf Management-Info nicht öffnen; Reportserver erzeugt einen geplanten Report zur konfigurierten Zeit.
Tracelinks: SyRS-077
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Nachvollziehbarkeit und Revisionsfähigkeit
Ebene: StRS
Typ: nicht-funktional (Zuverlässigkeit/Compliance)
Akteur: Geschäftsführung, Wirtschaftsprüfer, Administrator
Vorbedingung: —
Fakt: Jede Belegänderung erzeugt eine vollständige Version (Kopf+Positionen) in *Versions-Tabellen; ChangeLog protokolliert Feldänderungen mit Alt-/Neuwert und Benutzer; AnlageLog protokolliert Belegereignisse; Belege tragen CreatedBy/ChangedBy inkl. erzeugender Anwendung und Programmversion; Rechnungsstorno hinterlässt Logeintrag.
Aussage: Das System soll alle geschäftsrelevanten Änderungen lückenlos nachvollziehbar machen: vollständige Belegversionshistorie, feldgenaues Änderungsprotokoll, Ereignisprotokolle und Urheber-/Versionskennzeichnung an jedem Datensatz.
Ergebnis: Jeder frühere Belegstand ist rekonstruierbar; Änderungen sind personenbezogen zuordenbar.
Belege:
- [PRIMÄR] docs/reference/receipts/receipts-backend-architecture.md (Version Tables 1:1, SaveAssetVersion-SQL) und ReceiptBL.SaveReceipt (Versionspflicht, WriteReceiptLogs) – Begründung: Versionsmechanik ist Kernbestandteil des Speicherwegs.
- [PRIMÄR] src/backend/Centron.Entities/Entities/ChangeTracking/ChangeLog.cs – Begründung: feldgenaues Änderungsprotokoll als Entität.
- [PRIMÄR] ReceiptBase.cs:46-52 (CreatedAt/-By, ChangedAt/-By, *ThroughApplicationVersion, ChangedThroughApplication) – Begründung: Urheberkennzeichnung im Datenmodell.
Prüfidee: Beleg zweimal ändern; es müssen zwei Versionsdatensätze existieren und der Ursprungszustand vollständig rekonstruierbar sein.
Tracelinks: SyRS-020, SyRS-072, SyRS-031
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-026
Titel: Datenschutz-Unterstützung (DSGVO)
Ebene: StRS
Typ: funktional, Sicherheit
Akteur: Datenschutzbeauftragter, Administrator
Vorbedingung: DSGVO-Lizenz und Recht ACCESS_DSGVO_MODULE
Fakt: Eigenes DSGVO-Modul (CentronDataSecurityAppModuleController) mit Recht DsgvoModule.ACCESS_DSGVO_MODULE; Entität OrderProcessingContractState (Auftragsverarbeitungsverträge); Einstellungsseite für AV-Verträge.
Aussage: Das System soll Datenschutzprozesse unterstützen, mindestens die Verwaltung von Auftragsverarbeitungsverträgen und einen rechtegeschützten DSGVO-Arbeitsbereich.
Ergebnis: Datenschutzrelevante Vorgänge sind zentral und zugriffsgeschützt verwaltbar.
Belege:
- [PRIMÄR] ModuleRegistration.cs:460-462 (DSGVO-Modul mit Recht und Lizenz) – Begründung: Modulzugang ist rechte- und lizenzgeschützt.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Documents/Dsgvo/OrderProcessingContractState.cs – Begründung: AV-Vertragsstatus im Code.
Prüfidee: Benutzer ohne ACCESS_DSGVO_MODULE sieht das DSGVO-Modul nicht.
Tracelinks: SyRS-080
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-027
Titel: Kommunikationsintegration (E-Mail, Telefonie, Kalender)
Ebene: StRS
Typ: funktional, Schnittstelle
Akteur: alle internen Benutzer
Vorbedingung: Konten/TAPI konfiguriert
Fakt: Mail-BL mit Vorlagen und Variablenersetzung; MailScanner-Anwendung (eigene ApplicationKind) und Virtual Mail Assistant-Rechte; TAPI-Server-Anwendung, TapiClientHub (SignalR), Telefonate-Modul; Kalender-Synchronisation (Exchange-Sync-Doku, CalendarSynchronizationSettings); Outlook Add-In als eigene Anwendung.
Aussage: Das System soll E-Mail (Versand über Vorlagen, automatisierte Eingangsverarbeitung), Telefonie (Anrufprotokolle, TAPI-Anbindung) und Kalender (Exchange-Synchronisation, Outlook-Integration) in die Vorgangsbearbeitung integrieren.
Ergebnis: Kommunikation wird am Vorgang (Ticket/Kunde) dokumentiert; Anrufe und Termine sind mit Stammdaten verknüpft.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs (MailScanner, MailScannerNET, TapiServer, CentronOutlookAddInPro) – Begründung: Integrationen als anmeldefähige Anwendungen.
- [PRIMÄR] src/webservice/Centron.Host/RealTimeServices/TapiClientHub.cs – Begründung: Telefonie-Echtzeitkanal implementiert.
- [SEKUNDÄR] docs/features/exchange-sync-bugprotokoll.md, docs/reference/architecture/tapi.md – Begründung: dokumentierte Exchange-/TAPI-Architektur.
Prüfidee: Eingehender Anruf mit bekannter Rufnummer öffnet/protokolliert den Kundenbezug im Telefonate-Modul.
Tracelinks: SyRS-073, SyRS-074, SyRS-075, SyRS-076
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-028
Titel: Elektronischer Datenaustausch mit Distributoren (EDI)
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer, Distributor (extern)
Vorbedingung: EDI-Konfiguration je Lieferant
Fakt: SupplierEdiBL mit herstellerspezifischen Teilimplementierungen (ALSO, ALSO CH, Alltron, Herweck, Komsa, OpenTrans 2.1); Ablauf: FTP/SFTP-Abruf, Formaterkennung, Parsing, Auftragszuordnung, Persistierung, EDI-Log.
Aussage: Das System soll Belege (Bestellbestätigungen, Lieferavis, Rechnungen) führender IT-Distributoren automatisiert abrufen, den eigenen Bestellungen zuordnen und verbuchen, mit vollständigem Verarbeitungsprotokoll.
Ergebnis: Lieferanten-Belege fließen ohne manuelle Erfassung in die Einkaufsbelegkette.
Belege:
- [PRIMÄR] docs/reference/edi/edi-architecture.md (Klassenliste SupplierEdiBL.Also/.Alltron/.Herweck/.Komsa/.Opentrans, Ablaufdiagramm, ApplyDistriToCentron) – Begründung: dokumentierte, im Code vorhandene Architektur (Gateway-Projekte Centron.Gateway.EDI_*).
- [PRIMÄR] src/backend/Centron.Interfaces/EDI/EDILogState.cs, EDIHeadState.cs – Begründung: Verarbeitungsstatusmodell existiert.
Prüfidee: Test-EDI-Datei (OpenTrans-Rechnung) einspielen; System muss sie der Bestellung zuordnen und einen EDI-Log-Eintrag mit Status erzeugen.
Tracelinks: SyRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-029
Titel: Produktionsaufträge
Ebene: StRS
Typ: funktional
Akteur: Produktionsmitarbeiter
Vorbedingung: Produktions-Lizenz
Fakt: Module Maschinenverwaltung und Produktionsaufträge (Lizenz ProductionManagement, ohne Rechteprüfung); ProductionOrderBL, ProductionOrderItemState; Nexus-Seite /production/overview.
Aussage: Das System soll einfache Produktionsaufträge (Zusammenbau/Konfektionierung) mit Maschinenbezug und Positionsstatus verwalten.
Ergebnis: Produktionsvorgänge sind planbar und im Web einsehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Production/ProductionOrderBL.cs, src/backend/Centron.Interfaces/Production/ProductionOrderItemState.cs – Begründung: Geschäftslogik und Statusmodell vorhanden.
- [PRIMÄR] ModuleRegistration.cs:824-832 – Begründung: Modulregistrierung mit Lizenz ProductionManagement.
Prüfidee: Produktionsauftrag anlegen; Positionsstatuswechsel müssen den definierten Enum-Werten folgen.
Tracelinks: SyRS-081
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-030
Titel: Projektverwaltung
Ebene: StRS
Typ: funktional
Akteur: Projektleiter, Vertriebsmitarbeiter
Vorbedingung: Projektrechte
Fakt: CRM-Projekte (CRMProjekt-Nummernkreis, ProjectsAppModuleController) und Ticket-Projekte (TicketProjects-Nummernkreis, TicketProjectBL) existieren; Belege können Projektnummern tragen (CheckIfProjectNumberIsNeeded, CheckCrmProjectShouldBeSet); Projektpreis-Import-Modul.
Aussage: Das System soll Projekte führen (Vertriebs-/CRM-Projekte und Abwicklungs-/Ticketprojekte), Belege Projekten zuordnen (auf Wunsch verpflichtend) und projektspezifische Preise unterstützen.
Ergebnis: Umsätze und Aufwände sind projektbezogen auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3717,3732 (CheckCrmProjectShouldBeSet, CheckIfProjectNumberIsNeeded) – Begründung: Projektzuordnung wird beim Belegspeichern geprüft.
- [PRIMÄR] NumberGroupEnum (CRMProject=24, TicketProject=29) – Begründung: eigenständige Projektnummernkreise.
- [PRIMÄR] ModuleRegistration.cs:539-541, 863-865 (Projekte, Projektpreis-Import) – Begründung: Module inkl. Rechten.
Prüfidee: Einstellung „Projektnummer erforderlich" aktivieren; Belegspeicherung ohne Projektnummer muss eine Rückfrage/Fehlermeldung erzeugen.
Tracelinks: SyRS-082, SyRS-022
Konsolidierung: Kandidat: zwei Projektwelten (CRM-Projekte vs. Ticket-Projekte) – fachliche Zusammenführung im Zielsystem prüfen.
Status: belegt
```
```
ID: StRS-031
Titel: Deutschsprachiger Markt und Zweisprachigkeit
Ebene: StRS
Typ: nicht-funktional (Benutzbarkeit)
Akteur: alle Benutzer
Vorbedingung: —
Fakt: Entwicklungsrichtlinie: alle Benutzertexte deutsch, Ressourcen in LocalizedStrings.resx (de) und .en.resx (en); Fehlermeldungen in BL sind deutsch; Schweiz-spezifische Einstellungen (SwitzerlandSettings, ESR-Felder) und Österreich-Format (ebInterface) existieren.
Aussage: Das System soll primär deutschsprachig sein (alle Benutzertexte, Fehlermeldungen), Englisch als zweite Oberflächensprache anbieten und länderspezifische Besonderheiten für DACH (Schweiz: ESR/QR-Zahlteil; Österreich: ebInterface) unterstützen.
Ergebnis: Benutzer arbeiten in Deutsch oder Englisch; DACH-Zahlungs-/Rechnungsformate sind verfügbar.
Belege:
- [PRIMÄR] docs/getting-started/general-structure.md („German-First Language Policy", resx-Struktur) – Begründung: verbindliche Richtlinie; resx-Dateien im Code vorhanden (z. B. CentronNexus SharedResource.resx/.en-US.resx).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Switzerland, ReceiptBL.FillEsrFields; src/apis/Centron.Api.EbInterface – Begründung: DACH-Sonderlogik implementiert.
Prüfidee: Umschalten der Oberflächensprache auf Englisch; Nexus-Oberflächentexte müssen aus .en-US.resx geladen werden.
Tracelinks: SyRS-015
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-032
Titel: Barverkauf und Kassenbuch
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter (Theke), Buchhalter
Vorbedingung: Kassenbuch-Rechte
Fakt: Nummernkreise Barangebot/Barrechnung; Rechteklassen Sales.Cashbox.BarInvoice/Accountingbook; CashBookBL/CashBookBookingBL verbuchen Zahlungen aus Belegen ins Kassenbuch; der neue SaveReceipt-Weg lehnt Bar-Belege derzeit ab („Aktuell werden leider noch keine Bar-Belege unterstützt.").
Aussage: Das System soll Barverkäufe (Barrechnung/Barangebot) und ein Kassenbuch mit automatischer Verbuchung von Barzahlungen unterstützen.
Ergebnis: Barzahlungen sind im Kassenbuch dokumentiert und mit Belegen verknüpft.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CashBooks/CashBookBookingBL.cs (UpdateCashBookBookingFromAsset) – Begründung: Kassenbuchbuchung aus Belegen ist codiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3764-3765 (Ablehnung von IsCashAsset im neuen Speicherweg) – Begründung: belegt Übergangszustand der Barbeleg-Unterstützung.
- [SEKUNDÄR] UserRightsConst.Sales.Cashbox (BarInvoice, Accountingbook) – Begründung: Rechtezuschnitt Kasse.
Prüfidee: Barrechnung im Altweg erzeugen; Kassenbuch muss die Zahlung ausweisen. Im neuen Speicherweg muss die dokumentierte Ablehnungsmeldung erscheinen.
Tracelinks: SyRS-064
Konsolidierung: nein
Status: belegt; Workaround (Bar-Belege im modernisierten Speicherweg blockiert – Altweg/WPF-Spezialmasken erforderlich)
```
```
ID: StRS-033
Titel: Sichere Benutzeranmeldung
Ebene: StRS
Typ: Sicherheit
Akteur: alle Benutzer, Administrator
Vorbedingung: Benutzerkonto existiert
Fakt: AppUser unterstützt Passwort-Anmeldung (SHA1-gehasht), Mindestlänge und Gültigkeitsdauer je Benutzer, zeitfensterbasierte Kontodeaktivierung, 2FA (UseTwoFactorAuthentication, TwoFactorValidDurationInDays, PIN-Validierung) und OpenID-Connect-Anmeldung (OpenIdConnectSubjectIdentifier, EntraIDUsersBL, „Anmelden mit Microsoft"-Doku); Login-Metadaten (Maschine, IP, Zeit) werden gespeichert.
Aussage: Das System soll die Anmeldung interner Benutzer absichern: Passwortrichtlinien (Mindestlänge, Ablauf), optionale Zwei-Faktor-Authentifizierung je Benutzer, alternative Anmeldung über OpenID Connect (Microsoft Entra ID) sowie Protokollierung der Anmeldungen.
Ergebnis: Nur authentifizierte Benutzer erhalten Zugriff; Anmeldungen sind nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Administration/AppUser.cs:20-62 (PasswordMinLength, PasswordValidDurationDays, IsAccountDisabled, UseTwoFactorAuthentication, OpenIdConnectSubjectIdentifier, Login*-Felder) – Begründung: Sicherheitsattribute im Datenmodell.
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs (ValidateAuthenticationPin) – Begründung: 2FA-Prüfung implementiert.
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs:186-205 (JWT-Bearer mit vollständiger Token-Validierung) – Begründung: OIDC-Tokenprüfung serverseitig.
- [SEKUNDÄR] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md – Begründung: dokumentierter Microsoft-Login.
Prüfidee: Benutzer mit aktivierter 2FA muss nach Passwort eine gültige PIN eingeben; abgelaufenes Passwort (PasswordValidDurationDays) muss zum Wechsel zwingen.
Tracelinks: SyRS-004, SyRS-007, SyRS-008, SyRS-009
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-034
Titel: Persönliche Arbeitsorganisation und Automatisierung
Ebene: StRS
Typ: funktional
Akteur: alle internen Benutzer, Support-Leitung
Vorbedingung: —
Fakt: Module Mein Tag (MyDay), Todo-Liste, Dashboard, Taskmanagement (Boards), Ticketprozess-Vorlagen, Erwartete Events (+Auswertung), Reportserver; Zeiterfassung erzeugt automatisch Zeitplan-Einträge (CreateOrUpdateTimeSchedule).
Aussage: Das System soll persönliche Arbeitssteuerung (Tagesplan, Aufgaben, Dashboards) und teamübergreifendes Taskmanagement inklusive automatischer Ereignisüberwachung (erwartete Events) bereitstellen.
Ergebnis: Mitarbeiter sehen Aufgaben/Termine gebündelt; ausbleibende erwartete Ereignisse werden erkannt.
Belege:
- [PRIMÄR] ModuleRegistration.cs (MyDayEditor, TodoList, CentronDashboard, TaskManagment mit SHOW_TASKMANAGEMENT, ExpectedEvents mit SHOW_EXPECTEDEVENTS) – Begründung: Modulbestand und Rechte.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs:411-419 (ScheduleBL.CreateOrUpdateTimeSchedule) – Begründung: automatische Verzahnung Zeiterfassung → Planung.
Prüfidee: Zeiterfassung anlegen; im MyDay-/Planungsbereich muss der zugehörige Zeitplan-Eintrag erscheinen.
Tracelinks: SyRS-078, SyRS-069
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-035
Titel: MSP-Geschäft mit RMM-Datenintegration
Ebene: StRS
Typ: funktional, Schnittstelle
Akteur: MSP-Betreiber, Buchhalter, externe RMM-Systeme
Vorbedingung: MSP-Lizenz; RMM-Konnektoren konfiguriert
Fakt: Anmeldefähige Monitoring-Konnektoren (NAble, GFIMax, InvenigateConnector mit ExpirationKind.MonitoringConnector); RmmController/RmmConnectionSettingsController; MSP-Collector/-Comparer/-Dashboard-Module; AutomaticFacturaBL.CreateSpecialArticleToContractFromMspEvaluation überführt MSP-Auswertungsdaten in Vertragspositionen.
Aussage: Das System soll Nutzungsdaten externer RMM-/Monitoring-Systeme entgegennehmen, je Kunde auswerten (Collector/Vergleich) und automatisiert in die Vertragsabrechnung überführen.
Ergebnis: MSP-Leistungen werden datenbasiert und periodengerecht fakturiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs:129-147 (CreateSpecialArticleToContractFromMspEvaluation) – Begründung: Übergabe MSP-Auswertung → Vertrag ist codiert.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs (NAble, GFIMax, InvenigateConnector) – Begründung: RMM-Konnektoren als Anwendungen.
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md – Begründung: dokumentierte RMM-Abrechnungslogik.
Prüfidee: MSP-Auswertungsposition erzeugen und in Vertrag überführen; Folgeabrechnung muss die Position fakturieren.
Tracelinks: SyRS-036, SyRS-084
Konsolidierung: nein
Status: belegt
```
@@ -0,0 +1,141 @@
# Traceability-Matrix
Konsolidierte Nachverfolgbarkeit über die drei Ebenen. Regeln:
- Jede SwRS-Anforderung referenziert (mindestens) eine SyRS-Anforderung; jede SyRS-Anforderung referenziert (mindestens) eine StRS-Anforderung.
- Die Tabelle in Abschnitt 1 zeigt je SwRS die **primäre** Kette (erstgenannter Tracelink); weitere Querbezüge stehen in den Anforderungsdokumenten selbst.
- Abschnitt 2 listet SyRS-Anforderungen, die in dieser Iteration noch **ohne SwRS-Verfeinerung** sind (bekannte Lücken, siehe Analysebericht).
- Backward-Traceability ergibt sich durch Lesen der Tabelle von rechts nach links.
## 1. Kette StRS → SyRS → SwRS (je SwRS eine Zeile)
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (primär) |
|---|---|---|---|
| StRS-017 | SyRS-001 | SwRS-001 | docs/getting-started/general-structure.md (Schichtenmodell) |
| StRS-017 | SyRS-001 | SwRS-002 | docs/getting-started/general-structure.md (ClassContainer/ILogic) |
| StRS-017 | SyRS-001 | SwRS-003 | Result<T>-Signaturen, z. B. ReceiptBL.SaveReceipt |
| StRS-017 | SyRS-002 | SwRS-004 | src/webservice/Centron.Host/CentronHost.cs:100-151 |
| StRS-033 | SyRS-004 | SwRS-005 | CentronHost.cs:155-205 (JWT-Validierung) |
| StRS-033 | SyRS-004 | SwRS-006 | Centron.BL/Administration/Logins/TicketBL.cs:37-247 |
| StRS-033 | SyRS-004 | SwRS-007 | CentronHost.cs:207-216; SecretKeyHandler.cs |
| StRS-017 | SyRS-003 | SwRS-008 | Centron.Controllers/Configuration/Routing/KebabCaseTransformer.cs |
| StRS-027 | SyRS-010 | SwRS-009 | Centron.Host/RealTimeServices/*.cs (4 Hubs) |
| StRS-002 | SyRS-018 | SwRS-010 | docs/reference/receipts/receipts-backend-architecture.md:174-255 |
| StRS-025 | SyRS-012 | SwRS-011 | docs/guides/database/database-conventions.md |
| StRS-025 | SyRS-012 | SwRS-012 | ScriptMethods/Scripts (764 Dateien); ScriptMethod11820.cs |
| StRS-017 | SyRS-014 | SwRS-013 | Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs |
| StRS-031 | SyRS-015 | SwRS-014 | LocalizedStrings*.resx; SharedResource*.resx |
| StRS-025 | SyRS-016 | SwRS-015 | docs/reference/security/developer-security.md |
| StRS-002 | SyRS-018 | SwRS-016 | Centron.Interfaces/CentronObjectKindNumeric.cs |
| StRS-017 | SyRS-006 | SwRS-017 | UserRightsConst.cs:10-31 (ID-Räume) |
| StRS-017 | SyRS-006 | SwRS-018 | docs/guides/development/check-userrights.md |
| StRS-018 | SyRS-005 | SwRS-019 | Centron.WPF.UI/Modules/ModuleRegistration.cs:414-907 |
| StRS-018 | SyRS-005 | SwRS-020 | docs/reference/security/licensing-system.md (LicenseManager-API) |
| StRS-018 | SyRS-005 | SwRS-021 | Centron.Interfaces/Administration/Logins/ApplicationKind.cs |
| StRS-033 | SyRS-008 | SwRS-022 | UsersBL.cs:65-107 (SHA1Decoder) |
| StRS-033 | SyRS-008 | SwRS-023 | UsersBL.cs:56-131 (ChangeOwnPassword) |
| StRS-033 | SyRS-007 | SwRS-024 | TwoFactorAuthenticationBL.cs:16-43 |
| StRS-033 | SyRS-004 | SwRS-025 | JwtAuthController.cs:23-53 |
| StRS-033 | SyRS-004 | SwRS-026 | AppUser.cs:38-48; TicketBL.SetLoginIP |
| StRS-002 | SyRS-018 | SwRS-027 | ReceiptBase.cs:11-71 |
| StRS-002 | SyRS-018 | SwRS-028 | Centron.Interfaces/Sales/Receipts/ReceiptState.cs |
| StRS-001 | SyRS-022 | SwRS-029 | ReceiptBL.cs:3535-3900 (SaveReceipt-Pipeline) |
| StRS-001 | SyRS-022 | SwRS-030 | ReceiptBL.cs:3562-3566 (Datumspflicht) |
| StRS-025 | SyRS-020 | SwRS-031 | ReceiptBL.cs:3568-3578 (Versionsvalidierung) |
| StRS-025 | SyRS-020 | SwRS-032 | receipts-backend-architecture.md:147-204 (Versionstabellen) |
| StRS-017 | SyRS-006 | SwRS-033 | ReceiptBL.cs:3603-3627 (Rechteprüfungen) |
| StRS-002 | SyRS-019 | SwRS-034 | ReceiptBL.cs:7265-7285; NumberGroupBL.cs:50-127 |
| StRS-002 | SyRS-019 | SwRS-035 | InvoiceSpecificLogic.cs:104-135 |
| StRS-002 | SyRS-030 | SwRS-036 | ReceiptBL.cs:3586-3593; ReceiptBase.cs:65 |
| StRS-001 | SyRS-022 | SwRS-037 | ReceiptBL.cs:3703-3761 (Prüfkatalog) |
| StRS-001 | SyRS-023 | SwRS-038 | ReceiptBL.cs:8636-8710 (Kreditlimit) |
| StRS-002 | SyRS-024 | SwRS-039 | ReceiptBL.cs:3692-3698 (Preisschutz) |
| StRS-002 | SyRS-029 | SwRS-040 | ReceiptBL.cs:8600-8634 (Kundenrabatt) |
| StRS-002 | SyRS-025 | SwRS-041 | ReceiptBL.cs:9753-9763; AssetCondition.ConcludeImmediatelyTheInvoice |
| StRS-023 | SyRS-071 | SwRS-042 | ReceiptBL.cs:9765-9803 (Belegordner) |
| StRS-025 | SyRS-031 | SwRS-043 | ReceiptBL.cs:8478-8498 (Exportwarnung) |
| StRS-002 | SyRS-026 | SwRS-044 | AssetLockBL.cs:27-104 |
| StRS-002 | SyRS-026 | SwRS-045 | ReceiptBL.cs:4808-4890 (ConcurrencyControlGuid) |
| StRS-003 | SyRS-027 | SwRS-046 | ReceiptInvoiceBL.cs:143-206 (CancelInvoice) |
| StRS-002 | SyRS-021 | SwRS-047 | ReceiptBL.cs:3676-3688, 3741, 3754 |
| StRS-032 | SyRS-064 | SwRS-048 | ReceiptBL.cs:3763-3765 (Barbeleg-Blockade) |
| StRS-025 | SyRS-072 | SwRS-049 | ReceiptLogBL.cs; AnlageArt-Wertetabelle |
| StRS-019 | SyRS-013 | SwRS-050 | ReceiptBL.cs:7309-7340 (BranchOrigin) |
| StRS-001 | SyRS-022 | SwRS-051 | ReceiptBL.cs:7287-7307 (Firmengruppen-SQL) |
| StRS-002 | SyRS-025 | SwRS-052 | AssetCondition.cs:13-55 |
| StRS-001 | SyRS-022 | SwRS-053 | Customer.cs:32-144 |
| StRS-013 | SyRS-057 | SwRS-054 | DunningBL.cs:160-182 (Mahnstopp) |
| StRS-013 | SyRS-057 | SwRS-055 | DunningBL.cs:341-806 (Zustellprofil/Variablen) |
| StRS-014 | SyRS-060 | SwRS-056 | OnlineBankingAccountTransactionsBL.cs:75-1345 |
| StRS-015 | SyRS-061 | SwRS-057 | BookKeepingExportBL.cs:201-209 |
| StRS-015 | SyRS-062 | SwRS-058 | InvoiceZugferdBL.cs; zugferd-field-mapping.md |
| StRS-014 | SyRS-059 | SwRS-059 | ReceiptBL.cs:3822-3826 (ESR) |
| StRS-004 | SyRS-032 | SwRS-060 | ReceiptContract.cs (contracts-backend.md:42-127) |
| StRS-004 | SyRS-033 | SwRS-061 | AutomaticFacturaBL.Contracts.cs:2101-2120 |
| StRS-004 | SyRS-034 | SwRS-062 | AutomaticFacturaBL.Contracts.cs:504-786 |
| StRS-004 | SyRS-035 | SwRS-063 | ReceiptBL.cs:3781-3788 (Kontingente) |
| StRS-004 | SyRS-036 | SwRS-064 | AutomaticFacturaBL.cs:129-427 |
| StRS-005 | SyRS-037 | SwRS-065 | Helpdesk.cs:17-72 |
| StRS-005 | SyRS-037 | SwRS-066 | HelpdeskStateBase.cs; HelpdeskCloseBL.cs:112 |
| StRS-005 | SyRS-038 | SwRS-067 | HelpdeskCloseBL.cs:108-157 |
| StRS-007 | SyRS-039 | SwRS-068 | EscalationBL.cs:215-345 |
| StRS-006 | SyRS-040 | SwRS-069 | HelpdeskTimerBL.cs:353-429 |
| StRS-006 | SyRS-041 | SwRS-070 | HelpdeskTimer.cs (+Base) |
| StRS-006 | SyRS-040 | SwRS-071 | HelpdeskTimerBL.cs:173-235 (Zuschläge) |
| StRS-006 | SyRS-042 | SwRS-072 | TimerBillingBL.cs:451-476 |
| StRS-005 | SyRS-044 | SwRS-073 | HelpdeskCreationTemplate.cs |
| StRS-010 | SyRS-050 | SwRS-074 | ReceiptArticleBookingBL.cs:296-366 |
| StRS-010 | SyRS-051 | SwRS-075 | ReceiptArticleBookingBL.cs:366-404 |
| StRS-010 | SyRS-052 | SwRS-076 | BarcodeState.cs; BarCode.cs |
| StRS-010 | SyRS-052 | SwRS-077 | ReceiptBL.cs:3667-3674, 3767-3771, 3873-3884 |
| StRS-011 | SyRS-053 | SwRS-078 | InventoryBL.cs:75-797 |
| StRS-012 | SyRS-054 | SwRS-079 | ReceiptBL.cs:3848-3851 |
| StRS-022 | SyRS-068 | SwRS-080 | WebReceiptState.cs |
| StRS-020 | SyRS-066 | SwRS-081 | Nexus-@page-Routen (Routenbäume) |
| StRS-020 | SyRS-066 | SwRS-082 | WebAccountBL.cs; UsersBL.cs:56-75 |
| StRS-027 | SyRS-073 | SwRS-083 | MailTemplateReferences.cs; DunningBL.cs:485 |
| StRS-034 | SyRS-079 | SwRS-084 | HelpdeskTimerBL.cs:421-466 (KI-Bewertung) |
| StRS-025 | SyRS-072 | SwRS-085 | ChangeLog.cs |
| StRS-017 | SyRS-003 | SwRS-086 | HelpdesksController.cs:16-67 |
| StRS-025 | SyRS-072 | SwRS-087 | ReceiptBL.cs:3616-3633 (Aktivitäten) |
| StRS-017 | SyRS-003 | SwRS-088 | Controllers/v1-Dateiliste; KebabCaseTransformer.cs |
## 2. SyRS-Anforderungen ohne SwRS-Verfeinerung (bekannte Lücken dieser Iteration)
Diese Systemanforderungen sind belegt, aber noch nicht auf Software-/Komponentenebene verfeinert. Sie sind Kandidaten für die nächste Iteration (siehe Analysebericht, Abschnitt Selbstbewertung).
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (primär) |
|---|---|---|---|
| StRS-018 | SyRS-011 | – (nur Startsequenz in SwRS-004) | CentronHost.cs:102-108 |
| StRS-033 | SyRS-009 | – (Feldmodell in SwRS-026) | AppUser.cs:28-32 |
| StRS-018 | SyRS-017 | – | CentronHost.cs OS-Weiche; docker/; deployment/ |
| StRS-002 | SyRS-028 | – (Teilabdeckung im Prüfkatalog SwRS-037) | ReceiptBL.cs:3703, 3745-3746 |
| StRS-005 | SyRS-043 | – | UserRightsConst.…Checklists; CentronChecklistItemState.cs |
| StRS-005 | SyRS-045 | – | NumberGroupEnum (RMA*); RmaClosedState.cs |
| StRS-008 | SyRS-046 | – | Supplier*-BL-Ordner; NumberGroupEnum:40-55 |
| StRS-009 | SyRS-047 | – | OrderSuggestionList-BL:589-1088 |
| StRS-028 | SyRS-048 | – | docs/reference/edi/edi-architecture.md |
| StRS-008 | SyRS-049 | – | SupplierPdfScanConfigs.cs |
| StRS-012 | SyRS-055 | – | Centron.Api.Gls; Centron.Api.Shipcloud |
| StRS-013 | SyRS-056 | – | OposBL.cs; OposRunBL.cs |
| StRS-014 | SyRS-058 | – | IncomingPaymentBL.cs |
| StRS-015 | SyRS-063 | – | ZugferdImportController.cs |
| StRS-016 | SyRS-065 | – | ReceiptProvision*-Entitäten |
| StRS-021 | SyRS-067 | – | Nexus /webcart-Routen; README.md |
| StRS-027 | SyRS-070 | – | CentronNexus.OutlookAddIn |
| StRS-027 | SyRS-074 | – | MailScannerBL.cs |
| StRS-027 | SyRS-075 | – | Centron.BL/Calendar; AppointmentRequestState.cs |
| StRS-027 | SyRS-076 | – | TapiClientHub.cs; ApplicationKind.TapiServer |
| StRS-024 | SyRS-077 | – | ModuleRegistration.cs:631-668; Statistics-BL |
| StRS-034 | SyRS-078 | – | Centron.BL/ExpectedEvents |
| StRS-026 | SyRS-080 | – | ModuleRegistration.cs:460-462; OrderProcessingContractState.cs |
| StRS-029 | SyRS-081 | – | ProductionOrderBL.cs; ProductionOrderItemState.cs |
| StRS-030 | SyRS-082 | – | TicketProjectBL.cs; NumberGroupEnum (Projekte) |
| StRS-025 | SyRS-083 | – | DataQualityService.md; HelpdeskTimerBL.cs:468 |
| StRS-035 | SyRS-084 | – | ModuleRegistration.cs:651-663; UserRightsConst.MspCollector |
## 3. Abdeckungsübersicht
- **StRS:** 35 Anforderungen; alle 35 durch mindestens eine SyRS-Anforderung verfeinert (vollständige Forward-Traceability StRS→SyRS).
- **SyRS:** 84 Anforderungen; 57 mit mindestens einer SwRS-Verfeinerung, 27 nur auf Systemebene (Tabelle Abschnitt 2; Zählung inkl. Teilabdeckungen konservativ).
- **SwRS:** 88 Anforderungen; jede referenziert mindestens eine existierende SyRS-ID (geprüft, siehe Analysebericht Konsistenzcheck).
- Jede Zeile in Abschnitt 1 nennt einen konkreten Artefaktbeleg; die vollständigen Beleglisten (inkl. Klassifikation PRIMÄR/SEKUNDÄR/KONTEXT) stehen in den Anforderungsdokumenten.
@@ -0,0 +1,201 @@
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Iteration 01, Lauf 22 (Lauf P)
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
> Ein Unterschied im Ergebnis lässt sich deshalb **nicht eindeutig** einer der beiden Ursachen
> zuschreiben. Für eine kausale Trennung fehlt der Zwischenpunkt Fable auf `high`.
>
> **Parallelbetrieb:** zwei gleichzeitige Läufe (P, Q). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt.** Tokenverbrauch, Anforderungsanzahl und Denials sind
> unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T21:09:18+02:00
- **Endzeit:** 2026-08-25T21:58:44+02:00
- **Dauer gesamt:** 00:49:26 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:49:23 (`duration_ms`) — API: 00:46:57
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-7adf`
- **Ablage:** `claude-fable-5/solo/max/`
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-58d2`
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** **`max`** – explizit per `--effort` gesetzt; Gegenprobe im Transkript: 235
Nachrichten, durchgängig `max`. **Erster Block, der vom bisherigen `high` abweicht.**
- **Modell:** `claude-fable-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.193 Input-/22 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 270 |
| Output-Tokens | 230.990 (davon 35.220 Thinking-Tokens) |
| Cache-Write-Tokens | 427.305 |
| Cache-Read-Tokens | 23.562.775 |
| Agent-Turns | 152 |
### Gesamtlauf (`modelUsage`)
| Messgröße | `claude-fable-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 270 | 4.193 | 4.463 |
| Output-Tokens | 230.990 | 22 | 231.012 |
| Cache-Write-Tokens | 427.305 | 0 | 427.305 |
| Cache-Read-Tokens | 23.562.775 | 0 | 23.562.775 |
| Tokens gesamt | 24.221.340 | 4.215 | **24.225.555** |
**Tokens gesamt: 24.225.555** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-fable-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `5155f938-271d-4e03-85fc-002f1702c15d`
- **Permission-Denials:** **1** – 1 × `Read` (ohne Kommandoangabe im Datensatz). Folgenlos, alle 7 Artefakte entstanden.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 59.716 B | 35 Anforderungen |
| `SyRS.md` | 118.720 B | 84 Anforderungen |
| `SwRS.md` | 98.672 B | 88 Anforderungen |
| `Traceability.md` | 10.513 B | konsolidierte Tabelle |
| `Hypothesen.md` | 9.138 B | Sammlung der `[HYPOTHESE]`-Aussagen |
| `Glossar.md` | 13.918 B | Domänenbegriffe |
| `Analysebericht.md` | 14.508 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **207 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 35 | 16,9 % |
| SyRS | 84 | 40,6 % |
| SwRS | 88 | 42,5 % |
| **Gesamt** | **207** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 86 | 41,5 % |
| Daten | 18 | 8,7 % |
| Sicherheit | 17 | 8,2 % |
| Schnittstelle | 15 | 7,2 % |
| funktional (Abrechnung) | 9 | 4,3 % |
| funktional / Daten | 8 | 3,9 % |
| funktional / Schnittstelle | 5 | 2,4 % |
| Architektur-Constraint | 4 | 1,9 % |
| Daten / funktional | 4 | 1,9 % |
| funktional, Schnittstelle | 3 | 1,4 % |
| (29 weitere) | 38 | 18,4 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 336 |
| davon `PRIMÄR` | 299 (89,0 %) |
| davon `SEKUNDÄR` | 30 (8,9 %) |
| davon `KONTEXT` | 7 (2,1 %) |
| Belege je Anforderung (Median) | 1 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 207 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 203 | 98,1 % |
| als `HYPOTHESE` gekennzeichnet | 4 | 1,9 % |
| als Workaround vermerkt | 4 | 1,9 % |
| Konsolidierungskandidaten | 17 | 8,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (68 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 207 von 207 mit Tracelinks (100,0 %) |
## Fable-Block (P, Q)
| Messgröße | **Lauf P** | **Lauf Q** |
|---|---:|---:|
| Anforderungen | 207 | 148 |
| — StRS / SyRS / SwRS | 35/84/88 | 26/56/66 |
| Tokens gesamt | 24.225.555 | 31.073.793 |
| Thinking-Tokens | 35.220 | 39.609 |
| Agent-Turns | 152 | 162 |
| Denials / Subagenten | 1 / 0 | 0 / 0 |
## Vergleich der drei Solo-Reihen
| | **Fable, `max`** (2 Läufe) | Opus, `high` (5 Läufe) | Sonnet, `high` (5 Läufe) |
|---|---|---|---|
| Anforderungen | 148 – 207 | 71 – 182 (Median 114) | 42 – 82 (Median 67) |
| Tokens gesamt | 24,22 – 31,07 Mio. | 13,56 – 24,86 Mio. (Median 22,76) | 4,36 – 12,60 Mio. (Median 5,05) |
| Thinking-Tokens | 35.220 – 39.609 | 11.239 – 24.179 | 10.470 – 22.957 |
| Agent-Turns | 152 – 162 | 116 – 195 | 67 – 107 |
## Anmerkungen/Auffälligkeiten
1. **Der höchste Solo-Verbrauch der gesamten Reihe – vom sparsamsten Modell.** Mit 24,22 und
31,07 Mio. Tokens übertrifft der Fable-Block sogar den teuersten Opus-Lauf (24,86 Mio.).
Da Fable als das schnellere und günstigere Modell gilt, ist der plausibelste Treiber der auf
`max` gesetzte Effort – bestätigen lässt sich das aus diesen Daten jedoch **nicht**, weil
Modell und Effort gleichzeitig gewechselt wurden.
2. **Deutlichster Hinweis auf den Effort: die Thinking-Tokens.** Mit 35.220 und 39.609 liegen
sie über allen 21 Vorläufen – der bisherige Höchstwert lag bei 24.179 (Opus, `high`), der
Sonnet-Solo-Median bei rund 12.000. Thinking-Tokens sind die unmittelbarste Wirkung der
Effort-Stufe, und sie steigen hier um Faktor 1,5 bis 3 gegenüber `high`. Das stützt die
Vermutung aus Anmerkung 1, ersetzt aber den fehlenden Kontrollpunkt nicht.
3. **Hohe Ausbeute bei den Anforderungen.** 148 und 207 Anforderungen liegen über dem
Opus-Median (114) und weit über dem Sonnet-Median (67) – bei einem Modell, das von den dreien
das schwächste ist. Die Anforderungsanzahl misst allerdings nur Menge, nicht Belegqualität;
eine inhaltliche Bewertung steht aus.
4. **Konsistent über beide Läufe.** Anforderungen 148 gegenüber 207 (Faktor 1,4), Tokens 24,22
gegenüber 31,07 Mio. (Faktor 1,3), Turns 152 gegenüber 162. Bei nur zwei Messpunkten ist das
keine belastbare Streuungsaussage, fügt sich aber in das Bild der übrigen Solo-Reihen ein,
die alle unter Faktor 3 bleiben.
5. **Was zur kausalen Trennung fehlt:** ein Fable-Block auf `high`. Er würde zeigen, ob der
Sprung im Verbrauch vom Modell oder vom Effort kommt. Alternativ ein Sonnet- oder Opus-Block
auf `max` – dann ließe sich der Effort-Effekt bei bekanntem Modell isolieren.
6. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2816620,"num_turns":152,"stop_reason":"end_turn","session_id":"5155f938-271d-4e03-85fc-002f1702c15d","total_cost_usd":43.66537800000002,"usage":{"input_tokens":270,"cache_creation_input_tokens":427305,"cache_read_input_tokens":23562775,"output_tokens":230990,"output_tokens_details":{"thinking_tokens":35220},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":427305,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1603,"cache_read_input_tokens":426879,"cache_creation_input_tokens":426,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":426},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4193,"outputTokens":22,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0043029999999999995,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-fable-5":{"inputTokens":270,"outputTokens":230990,"cacheReadInputTokens":23562775,"cacheCreationInputTokens":427305,"webSearchRequests":0,"costUSD":43.66107500000002,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-fable-5","provider":"firstParty"}},"permission_denials":[{"tool_name":"Read","tool_use_id":"toolu_01W6E1Yo6fxnq1K4j83jcDDL","tool_input":{"file_path":"C:\\Users\\CHRIST~1\\AppData\\Local\\Temp\\claude\\C--DEV-MasterArbeit-QuellCode-CentronERP\\5155f938-271d-4e03-85fc-002f1702c15d\\tasks\\bm3b61zcw.output"}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Der RRE-Lauf ist abgeschlossen. Alle sieben Ergebnisdokumente liegen im Zielverzeichnis `...\\01_Lauf_2026-08-25_210903_fable5_solo_v3.6.0-7adf\\Ergebnisse\\`; die analysierte Codebasis blieb unverändert (git status leer).\n\n**Ergebnisübersicht**\n\n| Datei | Inhalt |\n|---|---|\n| `StRS.md` | 35 Stakeholder-Anforderungen (Akteure, Geschäftsziele je Fachdomäne) |\n| `SyRS.md` | 84 Systemanforderungen in 8 Blöcken (Architektur/Betrieb, Belegwesen, Verträge, Helpdesk, Einkauf/Lager, Finanzen, Portale, Querschnitt) |\n| `SwRS.md` | 88 Software-Anforderungen auf Komponenten-/Algorithmusebene (u. a. SaveReceipt-Pipeline, Storno-Algorithmus, Nummernvergabe, Negativbuchungs-Freigabe, Eskalationsberechnung) |\n| `Traceability.md` | Vollständige Kette StRS→SyRS→SwRS (88 Zeilen) plus Lückenliste: 27 SyRS noch ohne SwRS-Verfeinerung |\n| `Hypothesen.md` | 16 Hypothesen mit fehlender Information und Klärungsweg |\n| `Glossar.md` | ~55 Domänenbegriffe, jeweils mit Artefaktbezug |\n| `Analysebericht.md` | Systemsteckbrief, Analysetiefe je Modul, Konsistenzcheck, Kennzahlen, Selbstbewertung |\n\n**Kennzahlen:** 207 Anforderungen, 336 Einzelbelege (89 % PRIMÄR, 9 % SEKUNDÄR, 2 % KONTEXT), 17 Konsolidierungskandidaten, 4 dokumentierte Workarounds, 1 Anforderung als HYPOTHESE herabgestuft (SyRS-009 Kontosperrung — Sicherheitsaussage ohne belegten Durchsetzungsort).\n\n**Konsistenzcheck (skriptgeprüft):** keine ID-Duplikate, keine Anforderung ohne Beleg/Prüfidee/Tracelink, keine Verweise auf nicht existierende IDs; alle 35 StRS sind durch SyRS verfeinert.\n\n**Fachlich bemerkenswerte Befunde:** Passwörter werden als ungesalzene SHA1-Hashes gespeichert (Ablösung im Zielsystem als zwingend markiert); nach FIBU-Export existiert nur eine Änderungs*warnung*, keine harte GoBD-Festschreibung; Barbelege sind im modernisierten Speicherweg blockiert („Aktuell werden leider noch keine Bar-Belege unterstützt\"); es bestehen deutliche Doppelstrukturen (Kunden- vs. Accounts-Modell, drei Abrechnungswege, RPC- vs. REST-API, WPF-Ticketliste vs. ServiceBoard), die als Konsolidierungskandidaten für die SaaS-Neuimplementierung ausgewiesen sind.\n\n**Bewusste Lücken dieser Iteration** (im Analysebericht priorisiert): XAML-Masken (1.233 Dateien) und damit maskenspezifische Pflichtfeld-Redundanz, Preisfindung im Detail, Finanzen-Läufe (OPOS/SEPA/Mahnlauf-Interna), RPC-Methodeninventar sowie Randmodule (DocuBoard, Riversuite-Familie u. a.).","ttft_ms":7306,"ttft_stream_ms":1604,"time_to_request_ms":34,"type":"result","duration_ms":2963099,"uuid":"f07f1199-716b-438d-98f8-e8f745ff49db","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 35 | 16,9 % |
| SyRS | 84 | 40,6 % |
| SwRS | 88 | 42,5 % |
| **Gesamt** | **207** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 86 | 41,5 % |
| Daten | 18 | 8,7 % |
| Sicherheit | 17 | 8,2 % |
| Schnittstelle | 15 | 7,2 % |
| funktional (Abrechnung) | 9 | 4,3 % |
| funktional / Daten | 8 | 3,9 % |
| funktional / Schnittstelle | 5 | 2,4 % |
| Architektur-Constraint | 4 | 1,9 % |
| Daten / funktional | 4 | 1,9 % |
| funktional, Schnittstelle | 3 | 1,4 % |
| (29 weitere) | 38 | 18,4 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 336 |
| davon `PRIMÄR` | 299 (89,0 %) |
| davon `SEKUNDÄR` | 30 (8,9 %) |
| davon `KONTEXT` | 7 (2,1 %) |
| Belege je Anforderung (Median) | 1 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 207 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 203 | 98,1 % |
| als `HYPOTHESE` gekennzeichnet | 4 | 1,9 % |
| als Workaround vermerkt | 4 | 1,9 % |
| Konsolidierungskandidaten | 17 | 8,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (68 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 207 von 207 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_210903_fable5_solo_v3.6.0-7adf\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T21:58:44.1855405+02:00
@@ -0,0 +1 @@
2026-08-25T21:09:18.7866475+02:00
@@ -0,0 +1,123 @@
# Analysebericht
**Lauf:** V1 Baseline (Prompt-only), Iteration 01 – 2026-08-25
**Gegenstand:** Gesamte Codebasis `C:\DEV\MasterArbeit\QuellCode\CentronERP` (c-entron ERP-Suite)
**Methode:** Statische Artefaktanalyse (RRE-Schritte 2–6), keine Ausführung, keine externen Werkzeuge/Agenten. Die Codebasis wurde ausschließlich gelesen.
---
## 1 Vorgehen (RRE-Schritte 2–6)
| Schritt | Umsetzung in diesem Lauf |
|---|---|
| 2 Artefakterhebung | Verzeichnis-/Mengengerüst (Dateizählung je Projekt), Solution-Struktur, Projekt-Doku (`docs/`, 56 Dateien), `README.md`, `CentronRights.md`, Konfigurationsdateien (`appsettings.json`, `WebServiceConfig`-Modell, `global.json`, `version.json`), DB-Migrationsbestand (764 Skriptmethoden), CI-Pipelines (`azure/`), Deployment (`deployment/`, `docker/`), Commit-Messages der jüngsten Historie. |
| 3 Technische Analyse | Modulkarten (WPF-Modulregistrierung, Nexus-Routen, REST-Interface-Partitionen, 36 Hintergrunddienste); Tiefenlesen der zentralen BL-Klassen (ReceiptBL ≈ 11.400 Zeilen partiell, ReceiptItemBL, AutomaticFacturaWebServiceBL, DunningRunBL, PaymentTransactionBL, BookKeepingExportBL, TicketBL, Authenticator-Familie, TwoFactorAuthBL, AccessTokenBL, ArticleStockBL, OrderSuggestionListBL, EscalationBL, HelpdeskBL, DsgvoBL, WebAccountBL, ReceiptPriceHelper); Entitätsmodelle (ReceiptBase/ReceiptContract, Helpdesk, HelpdeskTimer, Article, Customer); Statusmaschinen (ReceiptState, WebReceiptState, DunningLevel, Mahnstufen); Rechtekatalog (UserRightsConst-Struktur). |
| 4 Semantische Interpretation | Ableitung fachlicher Regeln aus Implementierung (z. B. Weiterverarbeitungsmatrix → Belegkette; DueKind-Formeln → Zahlungsziele; Limitberechnung → Kreditrisiko-Politik; Ticket-/Lizenzlogik → Sicherheits-/Kommerzmodell). Trennung Fakt/Aussage in jeder Anforderung. |
| 5 Formalisierung | 148 Anforderungen im vorgegebenen Format (26 StRS, 56 SyRS, 66 SwRS) mit Vorbedingung, Fakt, Soll-Aussage, Ergebnis, Prüfidee. |
| 6 Traceability | Bidirektionale Verlinkung StRS↔SyRS↔SwRS in jedem Anforderungsblock plus konsolidierte Matrix (`Traceability.md`, eine Zeile je SwRS mit primärem Pfad und Artefaktbeleg). |
Belegklassifikation: PRIMÄR = durchgesetzte Regel im Code/DB-Struktur; SEKUNDÄR = UI-/Modul-/Konfigurationsartefakt; KONTEXT = Doku/Kommentar/Commit. Risikobereiche (Sicherheit, Abrechnung, Berechtigungen) wurden nur mit PRIMÄR-Beleg als Anforderung aufgenommen (automatisiert geprüft, siehe Abschnitt 4); Unsicheres steht ausschließlich in `Hypothesen.md` (18 Hypothesen).
## 2 Artefaktinventar (Auszug)
- **Quellcode:** ~17.000 Quelldateien (cs/xaml/razor). Größte Projekte: Centron.WPF.UI (6.321), Centron.WebServices.Core (2.530), Centron.BL (2.068), CentronNexus (1.222), Centron.Entities (1.185), Centron.DAO (1.131).
- **Backend:** Centron.BL (≈90 Fachbereiche), Centron.DAO (NHibernate-Mappings, Repositories, TemporaryEntities), Centron.Entities, Centron.Interfaces, Centron.Gateway, Centron.Common.
- **Clients:** WPF (DevExpress), Blazor „Nexus" (ServiceBoard/Kundenportal/WebCart/WebOffer/Signing), Outlook-Add-In.
- **Dienste:** Centron.Host (ASP.NET Core, REST + WCF-Bridge + SignalR + Swagger), 36 Hintergrunddienste, Windows-Service/Console/Linux/Docker-Hosting.
- **Integrationen:** apis/ (ITscope, Icecat, COP, EGIS, FinAPI, GLS, Shipcloud, EbInterface), EDI-Gateways (ALSO, ALSO CH, Alltron, Herweck, Komsa, OpenTrans), docuFORM (Root).
- **DB-Migrationen:** 764 ScriptMethod-Klassen (Nr. 10184–11820) + Legacy-XAML-Skriptsammlungen + RecurringScriptMethods.
- **Doku:** docs/ mit Architektur-, Datenbank-, Rechte-, Sicherheits-, EDI-, Beleg- und ZUGFeRD-Referenzen; CentronRights.md (159 Zeilen Rechtesemantik Helpdesk).
- **Build/Release:** Azure-Pipelines (build/tests/regression/docker/analyze), Nerdbank.GitVersioning, WixSharp-Installer, StrongNaming.
- **Tests:** Centron.Tests.EndToEnd, .Integration, CentronNexusTests, PlaywrightTests, backend-/shared-/apis-Tests.
## 3 Modul-/Komponentenübersicht mit Analysetiefe
Legende: **V** = vertieft (Kernlogik gelesen, Regeln extrahiert) · **T** = teilweise (Struktur + Stichproben) · **S** = strukturell (nur Existenz/Einordnung) · **N** = nicht analysiert
| Bereich | Tiefe | Ergebnis im Anforderungs-Set |
|---|---|---|
| Belegwesen Verkauf (Angebot→Gutschrift, Vertrag) | **V** | SyRS-001…015, SwRS-005…025; SaveReceipt-Pipeline, Weiterverarbeitung, Versionierung, Nummern, Sperren |
| Preisberechnung/Rundung | **V** | SyRS-013, SwRS-019 (Formeln inkl. CH-Rundung) |
| Preisfindung/Preismatrix/Aktionspreise | **V** | SyRS-046/056, SwRS-055/065 |
| Vertragsabrechnung (Intervall, Zähler, RMM, Sammelrechnung, Importe) | **V** | SyRS-016…019, SwRS-026…030 |
| Mahnwesen | **V** | SyRS-020, SwRS-031 |
| FiBu-Export (DATEV/Abacus/custom) | **V** (Kernpfade) | SyRS-021, SwRS-032 |
| E-Rechnung ZUGFeRD/XRechnung | **T** | SyRS-022, SwRS-033; Versionsstand als H-13 offen |
| SEPA/Zahlungseingang/OPOS | **V** | SyRS-023/024, SwRS-034 |
| Authentifizierung/2FA/Tickets/Lizenzen/AccessTokens | **V** | SyRS-025…031, SwRS-035…041 |
| Rechteverwaltung (Katalog + Durchsetzung) | **V** | SyRS-029, SwRS-039/022; Katalog vollständig gesichtet, Einzelrechte nur exemplarisch |
| Webservice-Infrastruktur (REST/WCF/SignalR/Versionierung) | **T** | SyRS-032, SwRS-042 |
| Hintergrunddienste | **T** (Katalog + 3 Dienste vertieft) | SyRS-033, SwRS-043 |
| Helpdesk/Tickets | **V** (Modell, Rechte, Eskalation) | SyRS-034/035, SwRS-044/045 |
| Zeiterfassung/TimerBilling | **V** (Modell) / **T** (Abrechnungsdetails) | SyRS-036/037, SwRS-046 |
| Lager/Bestand/EK-Fortschreibung/Seriennummern | **V** | SyRS-038…040, SwRS-047…049 |
| Bestellvorschlag | **V** (SQL) | SyRS-041, SwRS-050 |
| Einkaufsbelege/Lieferantenkette | **T** | SyRS-004, SwRS-009/023 |
| Nexus Web (Routen, Konfiguration) | **T** | SyRS-042, SwRS-051 |
| WebCart | **T** | SyRS-043, SwRS-052 |
| WebOffer/C-Sign | **V** (Zustandslogik) | SyRS-044, SwRS-053 |
| Lieferanten-EDI | **T** (Architektur + Dienst) | SyRS-045, SwRS-054 |
| DSGVO/SEPA-Online-Dokumente | **V** | SyRS-047, SwRS-056 |
| Protokollierung/ChangeTracking | **V** | SyRS-048, SwRS-057 (Befund: Feld-Audit ungenutzt) |
| Lokalisierung | **T** | SyRS-049, SwRS-058 |
| Betrieb/Konfiguration/Migrationen | **V** | SyRS-050/051, SwRS-004/059/060/066 |
| Mailversand | **T** | SyRS-052, SwRS-061 |
| Reporting/FastReport | **T** | SyRS-053, SwRS-062 |
| Provisionen | **S** | SyRS-054, SwRS-063 (nur Komponentenebene) |
| Produktion | **S** | SyRS-055, SwRS-064 |
| CRM/Kampagnen/Umfragen | **S** | in StRS-010 subsumiert |
| Statistik/Management-Info/MSP-Dashboards | **S** | StRS-022; Kennzahlformeln offen (H-16) |
| Inventur, Kommissionierung | **S** | in StRS-008 subsumiert; Detailregeln offen |
| TAPI/Telefonie | **N** (nur Existenz) | H-17 |
| Exchange-Sync/Kalender | **N** (nur Existenz + Bugprotokoll) | H-18 |
| MailScanner, DocuBoard, PasswordManager, VideoPortal, SocialMedia, TradePool, ItPlanner, Chats, KI-Module, MyDay/MyCentron, TaskManager, Checklisten, RMA-Details, Import-Framework, IndexSearch, Customizations/CustomTables, MassUpdate, Mobile, Kalender | **N**/**S** | nicht anforderungsseitig erfasst (siehe 5.3) |
| Externe APIs FinAPI (Onlinebanking), GLS/Shipcloud (Versand), EbInterface (AT), Icecat | **S** | nur als Integrationsinventar (SwRS-066/SyRS-046) |
| Kassenmodul (Barrechnung/Kassenbuch) | **T** | bewusst als Hypothese H-01 (Obsolete-Widerspruch) |
## 4 Konsistenzcheck über das gesamte Anforderungs-Set
Automatisierte Prüfung (Textanalyse über StRS.md, SyRS.md, SwRS.md) am Ende des Laufs:
| Prüfung | Ergebnis |
|---|---|
| Doppelte oder mehrfach vergebene IDs | **0 Befunde** (26 StRS, 56 SyRS, 66 SwRS, alle eindeutig) |
| Anforderungen ohne Beleg | **0 Befunde** (jede Anforderung ≥ 1 klassifizierter Beleg) |
| Tracelinks auf nicht existierende IDs | **0 Befunde** (alle referenzierten IDs existieren) |
| Formatvollständigkeit (13 Pflichtfelder je Anforderung) | **0 Befunde** (alle Felder in allen 148 Anforderungen vorhanden) |
| Ebenen-Traceability (SyRS→StRS, SwRS→SyRS, StRS→SyRS) | **0 Befunde** (bidirektional vollständig) |
| Risikoregel: Typ „Sicherheit" ohne PRIMÄR-Beleg | **0 Befunde** |
| Risikoregel: Abrechnungs-/Preis-/Rechte-/Lizenzbezug ohne PRIMÄR-Beleg | **0 Befunde** |
| Statusverteilung | 140 × `belegt`, 8 × `belegt; Workaround`, 0 × `HYPOTHESE` in den Spezifikationen (18 Hypothesen separat in Hypothesen.md) |
Während der Erstellung wurden fünf Tracelink-Asymmetrien gefunden und korrigiert (StRS-011, StRS-022, StRS-023, StRS-026, SyRS-004), bevor der finale Check lief.
## 5 Selbstbewertung
### 5.1 Was wurde vollständig, was stichprobenhaft, was gar nicht analysiert?
- **Vollständig (für Spezifikationszwecke):** Die Kern-Wertschöpfung – Belegkette inkl. aller Speicher-Validierungen, Preisfindung/-berechnung, Vertrags-/Zähler-/RMM-Abrechnung, Mahnwesen, SEPA, FiBu-Export-Kernpfade, Authentifizierung/Sitzungen/2FA/Lizenzen/Rechte-Durchsetzung, Lagerbewertung, Bestellvorschlag, Eskalation, Online-Annahme (C-Sign), DSGVO-Dokumente, Betriebs-/Migrationsmodell. Diese Bereiche tragen 90 % der Anforderungen und nahezu alle PRIMÄR-Belege mit Zeilenangaben.
- **Stichprobenhaft:** Nexus-Web (über Routen und Konfiguration, nicht je Seite), REST-API (Muster statt Methodenvollständigkeit), Hintergrunddienste (3 von 36 vertieft), EDI (Architektur + Dienst, nicht je Lieferantenparser), Reporting (Pipeline, nicht Reportinhalte), Einkaufsbelege (Kette + Dubletten, nicht alle Detailregeln), E-Rechnung (Erzeugungspfad, nicht Feld-für-Feld).
- **Gar nicht / nur Existenz:** TAPI, Exchange-Sync, MailScanner, DocuBoard, PasswordManager-Innenleben, VideoPortal, SocialMedia, TradePool, ItPlanner, KI-Module, MyDay/TaskManager/Checklisten im Detail, RMA-Werkstattprozesse, IndexSearch, CustomTables/Customizations, Mobile, Statistik-Kennzahlformeln, Versand-APIs (GLS/Shipcloud), FinAPI-Onlinebanking, Icecat-Katalogdaten. Der WPF-UI-Layer (6.321 Dateien) wurde bewusst nur über Modulregistrierung und gezielte Belege erfasst, nicht maskenweise.
### 5.2 Wo war der Beleg dünn?
- **StRS-Ebene systembedingt interpretativ:** Geschäftsziele sind Rückschlüsse aus Implementierung + Doku; alle StRS stützen sich aber auf mindestens einen PRIMÄR-Beleg der zugehörigen Systemfunktion.
- **SEKUNDÄR-/KONTEXT-lastig:** SwRS-001/002 (Architekturmuster – Hauptquelle Doku, PRIMÄR nur exemplarisch), SwRS-004 (DB-Konventionen – Doku + Beispiel-DDL), SyRS-045-Teilaspekte (185-Tage-Bereinigung nur aus Doku), SwRS-038 (ApplicationKind-Inhalte primär aus Doku, Datei selbst nicht geöffnet), H-13/H-14 (E-Rechnungs-Versionsstand, Lizenzbezug). Diese Stellen sind in den Belegen entsprechend gekennzeichnet.
- **Nicht verifizierte Kataloginhalte:** LicenseGuids.cs/ApplicationKind.cs wurden über Verwendungsstellen und Doku belegt, nicht Zeile für Zeile gelesen; ebenso die vollständige Rechteliste (nur Struktur + Einzelrechte).
- **Workaround-Kennzeichnungen (8):** SwRS-002 (Doppelimplementierung), SwRS-005 (TemporaryEntities-Speicherpfad), SwRS-015 (Mindestpreis-Re-Auth inkompatibel mit Entra-Login), SwRS-022 (Client-Trust bei Neubelegen), SwRS-033 (ZUGFeRD-Eigenimplementierung), SwRS-035 (SHA-1 ungesalzen), SwRS-057 (ungenutztes Feld-Audit), SwRS-060 (Excel-Nummernreservierung). Diese sind für die Migrationsvalidierung priorisiert zu prüfen.
### 5.3 Erkenntnisse für Folge-Iterationen
1. **Sicherheits-/Compliance-Klärung zuerst:** H-01 (Kasse/TSE), H-02 (GoBD), H-06 (Preisrechte-Lücke), SwRS-035 (SHA-1) – Abrechnungs- und Compliance-Risiken mit direktem Einfluss auf die Zielarchitektur.
2. **Portal-Berechtigungen für Belege** (H-15): gezielte Analyse der CustomerPortal-Belegabfragen in Nexus/WebServiceBL.
3. **Kennzahl-Reverse-Engineering** (H-16): Statistik-NamedQueries extrahieren und als testbare Kennzahldefinitionen formalisieren.
4. **Nicht erfasste Nebenmodule** (TAPI, Exchange-Sync, MailScanner, RMA, PasswordManager, MyDay/TaskManager, CustomTables): je Modul eine Kurz-Iteration nach dem Muster dieses Laufs; erst danach ist „gesamte Codebasis" auch anforderungsseitig abgedeckt.
5. **Katalog-Extraktion automatisieren:** Vollständige Listen (alle ~1.000 Rechte-IDs, alle LicenseGuids, alle AppSettings-Konstanten, NumberGroup-Arten, ReceiptLogKind-Werte) sind mechanisch extrahierbar und würden die SwRS-Datenanhänge präzisieren.
6. **End-to-End-Tests als Anforderungsorakel nutzen:** tests/Centron.Tests.EndToEnd speichert Belege über die reale Pipeline und vergleicht Legacy-Tabellenwerte – wertvolle Quelle zur Verifikation der SwRS-Formeln (z. B. SwRS-016/019) in einer Folge-Iteration.
7. **Konsolidierungsentscheidungen vorbereiten:** Die im Feld `Konsolidierung` markierten Kandidaten (mehrfache Abrechnungswege, mehrfache Preisquellen, doppelte Ticket-UIs, Doppel-Zugriffspfad BL/WS, mehrere Protokollmechanismen, Pflichtfeld-Mechanismen) sollten vor der Zielarchitektur als eigene Entscheidungsliste aufbereitet werden.
### 5.4 Grenzen dieses Laufs
- Aussagen beruhen ausschließlich auf statischer Analyse; Laufzeitverhalten (z. B. tatsächliche Dialogfolgen, Performanz) wurde nicht beobachtet.
- Zeilenangaben beziehen sich auf den analysierten Commit-Stand (Branch main, letzter Commit 79c1142f48 „Versuchsbasis: KI-Assistenz-Konfigurationen entfernt").
- Die deutschsprachigen Soll-Aussagen sind Interpretationen; die Validierung durch Fachexperten (RRE-Schritt 7) steht aus und ist über die Prüfideen je Anforderung vorbereitet.
@@ -0,0 +1,77 @@
# Glossar
Domänenbegriffe der c-entron-Codebasis, wie sie in StRS/SyRS/SwRS verwendet werden. Technische Bezeichner (Klassen, Tabellen, Spalten) bleiben in Originalsprache. Jeder Begriff nennt die Artefaktquelle, aus der er abgeleitet wurde.
| Begriff | Definition | Artefaktquelle |
|---|---|---|
| **Beleg** | Oberbegriff für Vertriebs- und Einkaufsdokumente (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag sowie Lieferanten-Pendants). Technisch: Ableitungen von `ReceiptBase`. | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs`; `docs/reference/receipts/receipts-backend-architecture.md` |
| **Belegkette / Weiterverarbeitung** | Überführung eines Belegs in einen Folgebeleg (z. B. Angebot → Auftrag → Lieferschein → Rechnung) unter Übernahme der Positionen mit Herkunftsreferenz (`OriginReceiptI3D`). Englisch im Code: *Forwarding*. | `ReceiptBL.ForwardReceipt`, `IReceiptSpecificLogic.CanBeForwardedInto()` |
| **Kopf / Position (Pos)** | Ein Beleg besteht aus einem Kopfdatensatz (`*Kopf`-Tabelle, z. B. `AufKopf`) und Positionsdatensätzen (`*Pos`-Tabelle, z. B. `AufPos`). | `docs/reference/receipts/receipts-backend-architecture.md` |
| **I3D** | Namenskonvention für Primärschlüssel („ID 3develop"): Spalte `I3D` als `int IDENTITY(1,1)`; Fremdschlüssel enden auf `...I3D`. | `docs/guides/database/database-conventions.md` |
| **Versionstabelle** | 1:1-Kopie einer Beleg-Tabelle (`*KopfVersions`, `*PosVersions`), in die bei jeder neuen Belegversion der vorherige Stand kopiert wird (Audit-Trail). | `docs/reference/receipts/receipts-backend-architecture.md`; `AssetHeadDAO.SaveAssetVersion` |
| **Belegversion** | Fortlaufende Versionsnummer eines Belegs (`ReceiptBase.Version`); Änderungen an Belegen erzeugen neue Versionen statt den Bestand zu überschreiben. | `ReceiptBL.CreateNewVersion` |
| **Belegstatus** | Zustand eines Belegs: `offen` (1), `abgeschlossen` (2), `storniert` (3). | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| **Nummernkreis (NumberGroup)** | Konfigurierbarer Zähler zur Vergabe fortlaufender Belegnummern, differenzierbar je Belegart und Filiale. | `ReceiptBL.UpdateReceiptNumber`, `NumberGroupBL.GetNextNumber` |
| **Filiale (Branch)** | Organisationseinheit; Belege, Mitarbeiter und Rechte können filialbezogen sein (`BranchI3D`). | `ReceiptBL.GetBranchForNewReceipt`; `UserRightsConst` (…ONLY_OWN_BRANCH-Rechte) |
| **Mandant (Mandator)** | Übergeordnete Firmen-/Buchungseinheit mit eigenen Bankdaten; verwaltet im Modul „Mandanten". | `ModuleRegistration.cs` (MandatorManagementAppModuleController); `MandatorBL.GetMandatorBankInfo` |
| **Zahlungskondition (PaymentCondition / AssetCondition)** | Stammdatum, das Fälligkeit (`DueKind`: sofort / +X Tage / Tag X des Folgemonats), Skonto und Zuordnung zu Belegarten definiert. | `ReceiptBL.UpdatePaymentDueDate`; `AssetConditionBL` |
| **Skonto-Ausschluss** | Artikelkennzeichen `NoEarlyPaymentDiscountAllowed`: Position ist von Skonto ausgenommen; wird in der Preisberechnung separat summiert. | `ReceiptPriceHelper.cs` (NotDiscountable…-Felder) |
| **Kreditlimit** | Kundenstammwert `CreditLimit` mit Berechnungsart `CreditLimitCalculationKind` (1 = netto, 2 = deaktiviert, sonst brutto); wird beim Belegspeichern gegen offene Belege geprüft. | `Customer.cs`; `ReceiptBL.CheckIfCustomerLimitIsReached` |
| **Mindestpreis (MinPrice)** | Artikelstammwert, den der Netto-Verkaufspreis einer Position nicht unterschreiten darf, außer ein Benutzer mit dem Recht `ALLOW_IGNORE_MINIMUM_PRICE` gibt frei. | `Article.MinPrice`; `ReceiptBL.CheckArticleMinPrices` |
| **Preisliste 1–4** | Vier Verkaufspreisfelder am Artikel (`Price1`–`Price4`); die Kundeneigenschaft `PriceList` (0–3) wählt den anzuwendenden Preis. | `Article.GetPrice(int pricelist)`; `Customer.PriceList` |
| **Staffelpreis (VolumePrices)** | Mengenabhängige Artikelpreise (`ArticleVolumePrices`), berücksichtigt bei der Preisfindung über die Menge. | `Article.VolumePrices`; `ArticleVolumePricesBL.cs` |
| **Sonderabsprache (SpecialAgreement)** | Kunden-/vertragsbezogene Preisvereinbarung, die bei Preisfindung Vorrang hat und die EK-Fortschreibung im Artikelstamm unterdrückt. | `PriceBL.GetSpecialAgreement`; `ArticleStockBL.UpdateArticlePurchasePrice` (Frühausstieg) |
| **Sonderpreis (AccountSpecialPrice)** | Kundenspezifischer Artikelpreis am Adressstamm; Grundlage des WebCart-Sortiments. | `AccountSpecialPrice.cs`; `README.md` (WebCart) |
| **Aktionspreis (ActionPrice)** | Zeitlich befristeter Einkaufs-Aktionspreis eines Distributors (`HerstellerArtikAktionspreis`), sichtbar in der Preismatrix. | `docs/reference/receipts/actionprice-system.md`; `ActionPriceBL.cs` |
| **Preismatrix (Preisspiegel)** | Vergleichsansicht paralleler Preisquellen je Artikel (ITscope, Artikelimport, COP, NEOS, TradersGuide, EGIS, Aktionspreise). | `docs/reference/receipts/actionprice-system.md`; `PriceMatrixViewModel.cs` |
| **Gleitender EK / Misch-EK** | Fortschreibung des Artikel-Einkaufspreises beim Wareneingang als gewichteter Durchschnitt; Alternativen je Artikel: letzter EK oder Fest-EK (`PurchasePriceAsKind`). | `ArticleStockBL.UpdateArticlePurchasePrice` |
| **Wareneingang (Intake)** | Zugangsbuchung in die Tabelle `Intake`; auch als Artikel-Kennzahl „unterwegs/eingebucht". | `OrderSuggestionListBL.cs` (Intake-Joins); `Article.Intake` |
| **Nebenlager (SecondaryStock)** | Zusätzliche Lagerorte neben dem Hauptlager, mit eigenem Bestand und eigenem EK je Artikel (`SecondaryStockArticle`). | `Article.SecondaryStocks`; `ArticleStockBL` |
| **Bestellvorschlag** | Ermittlung des Beschaffungsbedarfs aus Auftragsbedarf + Mindestbestand − Bestand − offenen Zugängen (inkl. Konsignation und Sonderabsprachen). | `OrderSuggestionListBL.cs` (SQL-Bedarfsformel) |
| **Seriennummer / Barcode** | Gerätebezogene Identifikation; seriennummernpflichtige Artikel (`ScanBarcode`) erfordern Erfassung, aktive Seriennummern blockieren Versionsrücknahme. | `BarcodeBL.cs`; `ReceiptBL.CreateNewVersion` (Prüfung „Seriennummern aktiv") |
| **Helpdesk / Ticket** | Serviceanfrage-Datensatz (`Helpdesk`, Tabelle `hlpdsk_requests`) mit konfigurierbaren Status, Prioritäten, Typen, Kategorien und Bearbeitern. | `Centron.Entities/.../Support/Helpdesk.cs`; `EscalationBL.cs` (SQL auf `hlpdsk_requests`) |
| **Eskalationsstufe** | Mehrstufige, arbeitszeitbewusste Eskalation überfälliger Objekte (Tickets, Liefertermine u. a.) mit Mailbenachrichtigung; Stufe wird am Ticket gespeichert (`EscalationLevel`). | `EscalationBL.cs`; `EscalationsService.cs` |
| **Timer (HelpdeskTimer)** | Zeiterfassungssatz zu einem Ticket (Start/Stopp, Pause, abrechenbar-Kennzeichen `Calculable`, Abrechnungsartikel, Zuschläge). | `HelpdeskTimer.cs` |
| **Leistungsnachweis** | Auswertung/Beleg der erfassten Zeiten; Timer tragen Kennzeichen `IsPrinted`, `IsSigned`, `SentAt`. | `HelpdeskTimer.cs`; Modul „Leistungsnachweise" in `ModuleRegistration.cs` |
| **TimerBilling („Vereinfachte Ticketabrechnung")** | Modul zur Überführung erfasster Ticketzeiten in Belege. | `ModuleRegistration.cs`; `ReceiptBL.CreateNewReceiptForHelpdekTimers` |
| **Vertragsabrechnung** | Periodische Erzeugung von Rechnungen aus Verträgen (`VertragKopf`/`VertragPos`) gemäß Abrechnungsintervall, inkl. Sammelrechnung mehrerer Verträge. | `AutomaticFacturaWebServiceBL.CreateInvoiceToContractComplete` |
| **Abrechnungsintervall** | `BillingIntervalKind` (täglich/monatlich/quartalsweise/jährlich) × `BillingIntervalDuration`; wirkt als Mengenmultiplikator bei der Abrechnung. | `docs/reference/receipts/contracts-backend.md`; `AutomaticFacturaWebServiceBL` (InvoiceIntervalCount) |
| **Kontingent** | Vertragsguthaben in Stunden oder Betrag (`ContingentUsedHours`, `ContingentLimitValue` …), das durch Leistungen verbraucht und überwacht wird. | `docs/reference/receipts/contracts-backend.md`; `ReceiptContractBL.ContractContingentBalanceCalculation` |
| **Klick-/Zählerabrechnung** | Abrechnung von Geräten (Drucker/Kopierer) nach Zählerständen inkl. Freikopien und Staffelpreisen. | `AutomaticFacturaBL.Contracts.cs` (Counter-Methoden); Modul „Klick-Zählerverwaltung" |
| **Stammblatt (MasterDataList)** | Geräte-/Datenliste, die einem Vertrag zugeordnet wird (z. B. Geräte mit Zählern). | `ReceiptContractBL.AddMasteDateListsToContract`; `MasterDataListOverviewAppModuleController` |
| **RMM** | Remote Monitoring & Management; externes System (z. B. „Riverbird"), dessen Nutzungsdaten über `RiverConnectionBL` abgerufen und fakturiert werden. | `docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md` |
| **MSP** | Managed Services Provider; MSP-Collector/-Auswertung aggregieren nutzungsbasierte Daten zur Abrechnung und Auswertung. | `MspCollectorsBL.cs`; Module „MSP-…" in `ModuleRegistration.cs` |
| **Sammelrechnung** | Eine Rechnung für mehrere Verträge desselben Kunden/Konzerns in einem Abrechnungslauf. | `AutomaticFacturaWebServiceBL.CreateInvoiceToContractComplete` (billingParams.Count > 1) |
| **Mahnstufe / Mahnlauf** | Dreistufiges Mahnwesen (`DunningLevel` 1–3) mit je Stufe gespeichertem Datum/Bearbeiter; Mahnläufe sind fortlaufend nummeriert (`DunningRunNumber`). | `DunningRunBL.UpdateInvoice`, `SaveDunningRun` |
| **OPOS** | Offene-Posten-Verwaltung (Modul „OPOS"). | `ModuleRegistration.cs` (OposOverviewAppModuleController) |
| **SEPA-Mandat** | Lastschriftmandat des Kunden (`MandatI3D` am Vertrag, `AuthorizationNumber` am Bankkonto); online bestätigbar als SEPA-Vertrag. | `contracts-backend.md`; `DsgvoBL.ConfirmOnlinePdfDocument` |
| **PAIN-Format** | XML-Format für SEPA-Lastschriftdateien; unterstützte Varianten: PAIN 008.001.01 (STUZZA), 008.003.02, 008.001.02, 008.001.02 GBIC 3, 008.001.08 GBIC 4. | `PaymentTransactionBL.cs` |
| **FiBu-Export** | Übergabe von Stammdaten/Bewegungsdaten an Finanzbuchhaltungssysteme (DATEV ASCII, DATEV XML Online 2020, Abacus, kundenspezifische Schnittstellen). | `BookKeepingExportBL.cs`; Gateways `DatevAscii`, `DatevXmlOnline2020` |
| **ZUGFeRD / XRechnung** | Strukturierte E-Rechnungsformate; eigene Implementierung mit Feldzuordnung, Datei wird als Mailanhang der Rechnung erzeugt; Leitweg-ID identifiziert Behördenempfänger. | `InvoiceZugferdBL.cs`; `docs/reference/zugferd-field-mapping.md`; `ReceiptBL.GetLeitwegID` |
| **Reverse Charge** | Umkehr der Steuerschuld; Artikelkennzeichen `IsReversecharge` wird in Positionen übernommen. | `Article.IsReversecharge`; `ReceiptItemBL.UpdateReceiptItemWithArticleInfo` |
| **WEEE** | Elektro-Altgeräte-Registrierungsnummer am Artikel; für bestimmte Belegarten Pflicht (`IsWeeeRequired`, z. B. Abholscheine). | `Article.WEEE`; `PickupListSpecificLogic.IsWeeeRequired()` |
| **AppUser** | Interner Benutzer des Systems (Tabelle `Sichbenu`), verknüpft mit einem Mitarbeiter (`Personal`). | `AppUserMaps.cs` (Table("Sichbenu")) |
| **WebAccount** | Zugangskonto für Endkunden (Portal/WebCart), verknüpft mit einer Kontaktperson eines aktiven Kunden. | `WebAccountBL.LoginWithWebAccount` |
| **Recht / Rechtegruppe** | RBAC-Modell: Rechte (IDs in `UserRightsConst`) werden über Gruppen an Benutzer vergeben; Prüfung per `AppRightsBL.CheckRightsFromUser`. | `UserRightsConst.cs`; `docs/guides/development/check-userrights.md` |
| **Einschränkendes Recht** | Recht, das Sichtbarkeit/Aktionen reduziert statt erweitert (z. B. „Tickets anzeigen – nur eigene"). | `CentronRights.md`; `HelpdeskBL` (ShowHelpdeskRight) |
| **Lizenz (LicenseGuid)** | Feature-/Produktfreischaltung als GUID mit optionalem Count, Ablaufdatum und Maximalversion; Quelle ist der Lizenzserver. | `docs/reference/security/licensing-system.md`; `LicenseGuids.cs` |
| **ApplicationKind** | Katalog der Anwendungen, die sich am Webservice anmelden dürfen; definiert je Anwendung Pflicht-/Sperr-Rechte und Ticket-Ablaufart. | `ApplicationKind.cs`; `Authenticator.ValidateRights` |
| **Sitzungs-Ticket** | Serverseitige Sitzungskennung nach Login (nicht zu verwechseln mit Helpdesk-„Ticket"); Standardablauf 30 Minuten, gleitend verlängert. | `TicketBL.cs` (TicketExpireInMinutes) |
| **Access-Token** | Persönlicher API-Schlüssel (SHA-256-gehasht gespeichert) mit Ablaufdatum, Aktivierung/Deaktivierung und Zugriffsprotokoll. | `AccessTokenBL.cs` |
| **ConcurrencyControlGuid** | GUID-Feld am Beleg für optimistische Nebenläufigkeitskontrolle. | `ReceiptBase` (Systemfelder laut `receipts-backend-architecture.md`); Parameter in `ReceiptBL.Update…`-Methoden |
| **AnlageLog / ReceiptLog** | Zentrales Belegprotokoll (Tabelle `AnlageLog`) mit `AnlageArt` = Belegart (1 Angebot … 22 Vertrag); erfasst Druck/Mail/EDI/Zahlungs-Ereignisse. | `receipts-backend-architecture.md`; `ReceiptLogBL.cs` |
| **ChangeLog** | Feldbezogene Änderungshistorie (alt/neu) über NHibernate-PreUpdate-Listener; Infrastruktur attributgesteuert. | `ChangeTrackingEventListener.cs`; `ChangeLog.cs` |
| **Soft Delete** | Löschkennzeichnung per `IsDeleted`/`DeletedByI3D`/`DeletedDate` statt physischem Löschen (Konvention für neue Tabellen). | `docs/guides/database/database-conventions.md` |
| **TemporaryEntities** | Legacy-Persistenzpfad: Beim Speichern werden moderne Beleg-Entities in Entities der deutschen Originaltabellen (`RechKopf`, `RechPos` …) synchronisiert. | `receipts-backend-architecture.md` („Critical Save Warning"); `Centron.DAO/Mappings/TemporaryEntities` |
| **ServiceBoard** | Web-Oberfläche (Blazor „Nexus") für Ticketbearbeitung (Kanban, MyDay, Suche, Zeiten, Planung). | `src/nexus/CentronNexus` (Routen `/serviceboard/...`) |
| **Kundenportal** | Web-Self-Service für Endkunden: Tickets, Dokumente, Belege, Formulare. | Routen `/customerportal/...` in `CentronNexus` |
| **WebCart** | B2B-Shop für Endkunden der Systemhäuser; Sortiment aus Kunden-Sonderpreisen. | `README.md` (Contributing/WebCart); Routen `/webcart/...` |
| **WebOffer / C-Sign / SharedDocument** | Online-Bereitstellung von Belegen per Token-Link zur Ansicht, Annahme (mit/ohne Signatur), Änderungswunsch oder Ablehnung. | `ReceiptBL.ChangeWebReceiptState`; `WebReceiptState.cs`; Routen `/weboffer/{Token}`, `/shareddocuments/{Token}/sign` |
| **Leitweg-ID** | Empfänger-Routing-Kennung für XRechnung an öffentliche Auftraggeber; je Kunde hinterlegt. | `ReceiptBL.GetLeitwegID` |
| **EDI** | Elektronischer Belegaustausch mit Lieferanten (ALSO, ALSO CH, Alltron, Herweck, Komsa, OpenTrans 2.1) über FTP/SFTP/FTPS. | `docs/reference/edi/edi-architecture.md`; `SupplierEdiBL.*` |
| **Eskalationsserver** | Lizenzpflichtiger Serverdienst, der Eskalationen alle 15 Minuten prüft. | `EscalationsService.cs`; `LicenseGuids.EscalationsServer` |
| **Skriptmethode** | Versioniertes Datenbank-Migrationsartefakt (`ScriptMethod<Nr>.cs`), das SQL-Änderungen idempotent ausführt; Nummern werden zentral reserviert. | `docs/guides/database/create-scripts.md`; `Centron.BL/Administration/Scripts/ScriptMethods/Scripts` |
| **Nexus** | Interner Name der Blazor-Webanwendung („c-entron Nexus aka c-entron Web"). | `README.md` |
| **DevExpress / FastReport** | Eingesetzte UI- bzw. Reporting-Komponenten (WPF-Controls, Blazor-Komponenten; Berichtserzeugung). | `Centron.BL.csproj` (FastReport.*, DevExpress.*); `README.md` |
| **Barrechnung / Kassenbuch** | Historische Kassenmodule; zugehörige Rechte sind im Code als `[Obsolete]` markiert (Status siehe Hypothesen). | `UserRightsConst.cs` (RIGHT_BARRIGHT_NUNG, RIGHT_KASSENBUCH mit `[Obsolete]`) |
| **IsCashAsset** | Kennzeichen „Barbeleg"; beeinflusst Preisberechnung (Bruttorechnung) und blockiert Weiterverarbeitung einer Barrechnung in eine Gutschrift über die UI. | `ReceiptPriceHelper` (isCashAsset-Parameter); `InvoiceSpecificLogic.CanBeForwardedIntoForUIOverwrite` |
@@ -0,0 +1,130 @@
# Hypothesen
Sammlung aller Aussagen, die sich aus den Artefakten **nicht eindeutig** ableiten ließen. Jede Hypothese nennt die vorhandenen Indizien (mit Belegklasse), die fehlende Information und den empfohlenen Klärungsweg (Schritt 7 der RRE-Methodenkette: Validierung durch Fachexperten).
---
## H-01 [HYPOTHESE] Status des Kassenmoduls (Barrechnung/Kassenbuch)
**Vermutung:** Die Kassenfunktionen (Barrechnung, Kassenbuch) sind fachlich noch relevant, aber technisch teilweise stillgelegt oder im Umbau; eine TSE-Anbindung (Kassensicherungsverordnung, § 146a AO) existiert nicht.
**Indizien:**
- [PRIMÄR] `UserRightsConst.cs` Zeilen 62–69: `RIGHT_BARRIGHT_NUNG` und `RIGHT_KASSENBUCH` sind `[Obsolete]` markiert; gleichzeitig existiert die Rechteklasse `Sales.Cashbox` mit Unterklassen `BarInvoice` und `Accountingbook` (Zeilen 1903–1938) ohne Obsolete-Markierung.
- [PRIMÄR] `InvoiceSpecificLogic.CanBeForwardedIntoForUIOverwrite` behandelt `IsCashAsset` (Barrechnungen) aktiv.
- Suche nach „TSE" / „Kassensich" im BL-Quellbaum ohne Treffer.
**Fehlende Information:** Produktentscheidung zum Kassenmodul; rechtliche Bewertung, ob Bargeschäfte über c-entron als „elektronisches Aufzeichnungssystem" i. S. d. KassenSichV laufen.
**Klärungsweg:** Fachexperten-Interview Produktmanagement; falls Kasse produktiv: TSE-Pflicht im Zielsystem als Anforderung ergänzen.
## H-02 [HYPOTHESE] GoBD-Konformität ist beabsichtigt, aber nicht als geschlossenes Konzept belegt
**Vermutung:** Versionstabellen, Beleg-Logs und Export-Schutz dienen (auch) der GoBD-Konformität (Unveränderbarkeit, Nachvollziehbarkeit); ein vollständiges GoBD-Konzept (Festschreibung, Verfahrensdokumentation, Datenzugriff Z1–Z3) ist im Code nicht nachweisbar.
**Indizien:**
- [PRIMÄR] Versionstabellen (`*KopfVersions`), `HandleIsAlreadyExported`, `ReceiptLogBL` (siehe SyRS-006, SyRS-021, SyRS-048).
- [KONTEXT] Kein Vorkommen von „GoBD"/„GDPdU" im Quellbaum (Suchbefund).
**Fehlende Information:** Ob und wie Festschreibungspflichten (z. B. unveränderliche Rechnungsnummern-/Inhalte nach Festschreibung) formell erfüllt werden; existiert eine Verfahrensdokumentation außerhalb des Repos?
**Klärungsweg:** Compliance-Verantwortliche befragen; für das Zielsystem GoBD-Anforderungen explizit spezifizieren (risikobehaftet, da Abrechnungsdomäne).
## H-03 [HYPOTHESE] Kein systematisches DSGVO-Lösch-/Anonymisierungskonzept für personenbezogene Daten
**Vermutung:** Es existiert kein automatisierter Lösch-/Anonymisierungsprozess für personenbezogene Daten nach Aufbewahrungsfristen; Löschungen erfolgen manuell.
**Indizien:**
- [PRIMÄR] `DocumentsCleanupService.cs` (Dokumentbereinigung) und EDI-Log-Bereinigung nach 185 Tagen sind die einzigen gefundenen automatischen Löschroutinen.
- [PRIMÄR] Soft-Delete-Konvention (`IsDeleted`) hält Daten physisch vor (database-conventions.md).
- [SEKUNDÄR] DSGVO-Modul adressiert AVV/SEPA-Dokumente, nicht Betroffenenrechte (Löschung/Auskunft).
**Fehlende Information:** Prozesse für Art. 17 DSGVO (Löschung), Auskunftsexporte, Aufbewahrungsfristen je Objektart.
**Klärungsweg:** Datenschutzbeauftragten einbinden; im Zielsystem Lösch-/Anonymisierungsanforderungen definieren.
## H-04 [HYPOTHESE] Keine quantifizierten Performance-/Lastanforderungen
**Vermutung:** Es gibt keine dokumentierten Antwortzeit- oder Durchsatzziele; Dimensionierung erfolgt erfahrungsbasiert.
**Indizien:**
- [PRIMÄR] Nur qualitative Mechanismen: `PerformanceTracer` in der Vertragsabrechnung, Batch-Größe 2000 (`AutomaticFacturaBL.SearchSpecialArticleToContractHead`), DB-Pool max 200 (`WebServiceConfig`), `TicketCache.MaxClosedTickets` 300.000 (Nexus), Performance-Test-Entities (`Entities/Administration/PerformanceTests`).
**Fehlende Information:** Zielwerte (Nutzerzahlen, Belegvolumen, Antwortzeiten), die eine SaaS-Neuimplementierung dimensionieren müssten.
**Klärungsweg:** Betriebsdaten von Bestandskunden erheben (Belege/Jahr, parallele Sessions); NFR-Workshop.
## H-05 [HYPOTHESE] Datensicherung/Wiederherstellung liegt vollständig außerhalb des Systems
**Vermutung:** Backup/Restore und Desaster-Recovery werden den MSSQL-Bordmitteln bzw. dem Kunden überlassen; das System selbst enthält keine Sicherungsfunktionen.
**Indizien:** Keine Backup-/Restore-Artefakte im Quellbaum (Suchbefund); Betriebsdoku (docs/operations) behandelt nur Build/Release.
**Fehlende Information:** Vertragliche/organisatorische Vorgaben zur Sicherung; RPO/RTO-Erwartungen der Kunden.
**Klärungsweg:** Betriebshandbuch/Onboarding-Unterlagen des Herstellers sichten; für SaaS-Zielbild sind RPO/RTO zwingend zu definieren.
## H-06 [HYPOTHESE] Preisrechte-Härtung hat bei Neubelegen eine ausnutzbare Lücke
**Vermutung:** Benutzer ohne Preisänderungsrecht könnten bei komplett neuen Belegen (ohne Vorversion/Ursprungsbeleg) über einen manipulierten Client abweichende Preise speichern.
**Indizien:**
- [PRIMÄR] `ReceiptBL.cs` Zeile 8105–8110: Kommentar „…So for now, we trust the client to not give us stupid prices when saving a completely new receipt" – der Rückfallpfad übernimmt den Client-Preis.
**Fehlende Information:** Ob kompensierende Kontrollen existieren (z. B. UI-seitige Sperren genügen nicht; ggf. nachgelagerte Prüfprozesse).
**Klärungsweg:** Sicherheitsbewertung mit Hersteller; im Zielsystem serverseitige Preisermittlung für Neubelege ohne Recht erzwingen. (Referenziert aus SyRS-029.)
## H-07 [HYPOTHESE] Generisches Feld-Audit wurde nie produktiv aktiviert
**Vermutung:** Die ChangeTracking-Infrastruktur (Attribut-gesteuertes Feld-Audit) wurde gebaut, aber nie auf Entities angewendet; feldgenaue Änderungsnachweise existieren nur dort, wo Spezial-Logs implementiert sind.
**Indizien:**
- [PRIMÄR] `ChangeTrackingEventListener.cs` vollständig implementiert; Suchbefund: keine Entity referenziert `ChangeTrackingConfigurationAttribute`/`TrackChangesAttribute`.
**Fehlende Information:** Historie der Entscheidung; ob Kunden Feld-Audits erwarten (z. B. Kundenstamm-Änderungen).
**Klärungsweg:** Entwicklerteam befragen; Audit-Anforderungen im Zielsystem explizit festlegen (siehe SwRS-057).
## H-08 [HYPOTHESE] Mandantenfähigkeit ist funktional begrenzt (kein strikt getrenntes Multi-Tenant-Modell)
**Vermutung:** „Mandanten" strukturieren Bankdaten/Zuordnungen innerhalb EINER Datenbank; eine harte Datentrennung (je Mandant eigene Daten-/Rechteräume) besteht nicht – mehrere Gesellschaften werden eher über Filialen abgebildet.
**Indizien:**
- [PRIMÄR] `MandatorBL.GetMandatorBankInfo` (Mandant über Mitarbeiter aufgelöst, für SEPA); Modul „Mandanten"; keine mandantenbezogenen Filter in den analysierten Suchpfaden (im Gegensatz zu Filialfiltern/-rechten).
**Fehlende Information:** Fachliche Definition „Mandant" im Produkt; Anforderungen an Mandantentrennung im SaaS-Zielbild.
**Klärungsweg:** Produktmanagement; für SaaS ist ein explizites Tenant-Modell zu spezifizieren.
## H-09 [HYPOTHESE] SLA-Fristen werden über Prioritäten/Eskalationstypen abgebildet, nicht über Verträge
**Vermutung:** Reaktions-/Lösungszeiten sind nicht je Servicevertrag hinterlegt, sondern ergeben sich aus Ticketpriorität + konfigurierten Eskalationstypen; ein vertragsindividuelles SLA-Modell fehlt.
**Indizien:**
- [PRIMÄR] `EscalationBL` verknüpft Eskalationstypen mit `TicketPriorityI3D`; Vertragsentity ohne SLA-Fristfelder (ReceiptContract.cs, Befund).
**Fehlende Information:** Ob Kunden vertragliche SLAs anders pflegen (z. B. über Prioritätszuordnung je Kunde).
**Klärungsweg:** Fachexperten Service; im Zielsystem SLA-Modell (je Vertrag/Kunde) entscheiden.
## H-10 [HYPOTHESE] Produktabgrenzung Riverbird / RiverSuite / RiverDivo / SupRemo
**Vermutung:** „Riverbird" ist das RMM-Partnerprodukt (Nutzungsdaten, Webservice-Login-Variante), „RiverSuite"/„RiverDivo"/„SupRemo" sind weitere Integrations- bzw. Schwesterprodukte mit eigenen Rechtebereichen; die genaue Produktlandschaft ist aus dem Code nicht ableitbar.
**Indizien:** [PRIMÄR] Namespaces/Ordner `RiverDivo`, `Riversuite`, `SupRemo`, `RiverConnectionBL`, `deployment/riverbird`; [KONTEXT] licensing-system.md erwähnt „Riverbird Web-Service".
**Fehlende Information:** Produkt-/Vertriebssicht der Integrationen; welche sind im Zielsystem fortzuführen?
**Klärungsweg:** Produktmanagement-Interview; Integrationsinventar priorisieren.
## H-11 [HYPOTHESE] docuFORM-Anbindung ist eine aktive Spezialintegration
**Vermutung:** `Centron.Api.docuFORM` (Root-Verzeichnis) bindet die docuFORM-Druckerverwaltung (MPS) an, vermutlich für Zählerdaten; Nutzungsgrad unklar.
**Indizien:** [PRIMÄR] Verzeichnis `Centron.Api.docuFORM` existiert auf Repo-Ebene; `DocuForm`-Ordner in `Centron.BL/DataExchange`.
**Fehlende Information:** Kundennutzung, Datenfluss, Relevanz fürs Zielsystem.
**Klärungsweg:** Herstellerbefragung; ggf. in Folge-Iteration Code-Analyse dieses Moduls.
## H-12 [HYPOTHESE] Kein Offline-Betrieb des Desktop-Clients
**Vermutung:** Der WPF-Client benötigt stets eine Verbindung (direkt zur DB oder zum Webservice); ein Offline-Modus mit Synchronisation existiert nicht.
**Indizien:** [PRIMÄR] Nur zwei ConnectionTypes (SqlServer, CentronWebServices) in der Architekturdoku; keine lokale Persistenz-/Sync-Infrastruktur gefunden.
**Fehlende Information:** Bestätigung, dass kein Offline-Szenario (z. B. Techniker vor Ort) unterstützt werden muss.
**Klärungsweg:** Anwenderbefragung Servicetechnik.
## H-13 [HYPOTHESE] E-Rechnungs-Versionsstand entspricht ZUGFeRD 2.1.1 und ist ggf. nicht auf aktuellem XRechnung-Stand
**Vermutung:** Die Eigenimplementierung basiert auf ZUGFeRD 2.1.1 (plus 1.0-Altpfad); neuere Normversionen (XRechnung 3.x, ZUGFeRD 2.3) sind möglicherweise nicht abgedeckt.
**Indizien:** [PRIMÄR] Eingebettete Spezifikation „ZUGFeRD-2.1.1 - Spezifikation_TA (1).pdf" im BL-Quellbaum; Partialklasse `InvoiceZugferdBL.Zugferd10.cs`; [KONTEXT] xrechnung.md verweist auf KOSIT-Werkzeuge und empfiehlt Bibliothekswechsel.
**Fehlende Information:** Tatsächlich erzeugte Profilversionen; Validierungsstand gegen aktuelle KOSIT-Regeln.
**Klärungsweg:** Datei-Erzeugung gegen KOSIT-Validator testen (dokumentierte Prüfidee SyRS-022); Normstand für Zielsystem festlegen.
## H-14 [HYPOTHESE] Lizenzdaten werden nicht zur Laufzeit vom Lizenzserver bezogen
**Vermutung:** Die Lizenzprüfung arbeitet gegen lokal (in der Kundendatenbank/-installation) hinterlegte Lizenzdaten; der Lizenzserver des Herstellers ist nur Quelle bei Ausstellung („c-entron Office"-Tool), nicht Laufzeitabhängigkeit.
**Indizien:** [KONTEXT] licensing-system.md: „single source of truth … license-server", zugleich Prüfung via lokalem `LicenseManager`; keine Online-Lizenzabruf-Logik im Anmeldepfad gefunden.
**Fehlende Information:** Wie Lizenzen zum Kunden gelangen (Datei? DB-Eintrag?) und wie Entzug wirkt.
**Klärungsweg:** Herstellerprozess erfragen; SaaS-Zielbild: Lizenzierung neu konzipieren.
## H-15 [HYPOTHESE] Beleg-Sichtbarkeit im Kundenportal folgt der WebAccount-Kundenzuordnung ohne feineres Rechtemodell
**Vermutung:** Portalnutzer sehen alle Belege „ihres" Kunden (Zuordnung über Kontaktperson→Adresse→Kunde); ein feingranulares Belegarten-/Belegebenen-Rechtemodell wie bei Tickets (WebRights) existiert für Belege nicht.
**Indizien:** [PRIMÄR] WebAccount-Validierung über Kundenkette (`WebAccountBL.LoginWithWebAccount`); WebRights-Konstanten betreffen Tickets (SHOWONLYOWNREQUESTS …); Portalrouten für Belege ohne erkennbare Rechteparameter.
**Fehlende Information:** Detailprüfung der Portal-Belegabfragen (nicht vollständig analysiert).
**Klärungsweg:** Folge-Iteration: `CustomerPortal`-Belegabfragen im Nexus-/WebServiceBL-Code analysieren.
## H-16 [HYPOTHESE] Kennzahldefinitionen der Statistik-/Managementmodule sind implizit
**Vermutung:** Die Kennzahlen (Analytics, Management Info, MSP-Dashboard, Vertragsauswertung) sind ausschließlich in SQL/Code definiert; es existiert keine fachliche Kennzahlenspezifikation.
**Indizien:** [PRIMÄR] Statistik-Namespaces mit NamedQueries; keine Kennzahl-Doku in docs/.
**Fehlende Information:** Verbindliche Definitionen (z. B. „Umsatz" brutto/netto, Stichtagslogik) für die Migration.
**Klärungsweg:** Folge-Iteration mit gezielter Analyse der Statistik-Queries + Fachabnahme.
## H-17 [HYPOTHESE] Telefonie-Integration (TAPI) ist funktional relevant, aber ungeprüft
**Vermutung:** TAPI-Server/Client-Integration (Anrufprotokoll, Telefonate-Modul, PhoneMondo) ist produktiv im Einsatz; Verhalten und Anforderungen wurden in dieser Iteration nicht analysiert.
**Indizien:** [PRIMÄR] `Entities/Tapi`, `TapiServer`, Modul „Telefonate", `ICentronRestService.PhoneMondo.cs`; [KONTEXT] docs/reference/architecture/tapi.md.
**Fehlende Information:** Fachliche Anforderungen der Telefonie.
**Klärungsweg:** Folge-Iteration.
## H-18 [HYPOTHESE] Exchange-/Kalender-Synchronisation hat bekannte Stabilitätsprobleme
**Vermutung:** Die Exchange-Synchronisation (Termine/Mails) ist fehleranfällig und wird über ein Bug-Protokoll nachgehalten; für das Zielsystem ist eine robuste Neukonzeption nötig.
**Indizien:** [KONTEXT] docs/features/exchange-sync-bugprotokoll.md (eigenes Bugprotokoll als Doku-Artefakt); [PRIMÄR] `ExchangeSyncService.cs`, EWS-Helper.
**Fehlende Information:** Aktueller Fehlerstand, fachlicher Soll-Umfang der Synchronisation.
**Klärungsweg:** Bugprotokoll auswerten, Anwenderinterviews.
---
**Verwendungshinweis:** Hypothesen sind KEINE Anforderungen. Vor Übernahme in eine Spezifikationsversion müssen sie durch Fachexperten bestätigt oder verworfen werden (RRE-Schritt 7). Risikoreiche Bereiche (H-01, H-02, H-06) sollten priorisiert geklärt werden, da sie Abrechnung/Compliance betreffen.
@@ -0,0 +1,544 @@
# StRS – Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (Reverse Requirements Engineering aus Codebasis `CentronERP`)
**Norm-Referenz:** ISO/IEC/IEEE 29148:2018, Informationselement StRS
**Erhebungsmethode:** Statische Analyse der Codebasis (Quellcode, Konfiguration, UI-Ressourcen, Projekt-Dokumentation). Keine Ausführung, keine Stakeholder-Interviews – alle Aussagen sind aus Artefakten rückgeschlossen.
## Zweck und Systemkontext
c-entron ist ein Warenwirtschafts- und Servicemanagement-System für IT-Systemhäuser im deutschsprachigen Markt (Hersteller: c-entron software gmbh / NEXOWARE). Es umfasst Vertrieb (Belegkette), Vertrags- und Serviceabrechnung (MSP-Geschäft), Helpdesk/Ticketing, Lager/Einkauf, Forderungsmanagement und Finanzbuchhaltungs-Anbindung. Der klassische Client ist eine Windows-WPF-Anwendung mit zentralem Webservice und MSSQL-Datenbank (On-Premises); ergänzend existiert die Web-Anwendung „Nexus" (ServiceBoard, Kundenportal, WebCart, Online-Signatur).
## Stakeholder (aus Artefakten abgeleitet)
| Stakeholder | Ableitung aus Artefakt |
|---|---|
| Vertriebsinnendienst / Verkauf | Rechtegruppen `UserRightsConst.Sales.*`, Belegmodule |
| Servicetechniker / Support-Mitarbeiter | Helpdesk-Module, ServiceBoard, `HelpdeskTimer` |
| Buchhaltung | Module Mahnung, OPOS, SEPA, Zahlungseingang, FiBu-Export |
| Lager-/Logistikmitarbeiter | Module Inventur, Kommissionierung, Wareneingang |
| Einkäufer | Lieferantenbelege, Bestellvorschlag, EDI, Preismatrix |
| Systemadministrator (des Kunden) | Rechteverwaltung, Mandanten, Einstellungen, ConnectionManager |
| Geschäftsführung | Module Management Info, Analytics, Provisionsauswertung |
| Endkunde des Systemhauses | Kundenportal, WebCart, WebOffer/C-Sign, WebAccounts |
| Lieferanten/Distributoren | EDI-Anbindungen, Preismatrix-APIs |
| Softwarehersteller (c-entron/NEXOWARE) | Lizenzsystem, Telemetrie, Versionierung |
| Steuerberater / Finanzverwaltung (mittelbar) | DATEV-Export, ZUGFeRD/XRechnung, Leitweg-ID |
---
## Anforderungen
```
ID: StRS-001
Titel: Durchgängige Vertriebs-Belegkette
Ebene: StRS
Typ: funktional
Akteur: Vertriebsinnendienst
Vorbedingung: Kunde ist im Adressstamm angelegt.
Fakt: Die Codebasis implementiert sieben Kundenbelegarten (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag) mit gemeinsamer Basisklasse und Weiterverarbeitungslogik zwischen den Belegarten.
Aussage: Das System soll den Vertriebsprozess als durchgängige Belegkette abbilden: Vom Angebot über Auftrag und Lieferschein bis zur Rechnung und ggf. Gutschrift, ohne dass Daten manuell neu erfasst werden müssen.
Ergebnis: Folgebelege übernehmen Positionen und Konditionen des Ursprungsbelegs; die Herkunft bleibt nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (ForwardReceipt, Zeile ~1548) – Begründung: implementiert die Überführung von Belegen in Folgebelege inkl. Positionsübernahme.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs – Begründung: gemeinsame Basisklasse aller Belegarten belegt das einheitliche Belegkonzept.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md – Begründung: beschreibt die Belegtypen-Hierarchie und deren Tabellen explizit.
Prüfidee: Ein Angebot mit 3 Positionen in einen Auftrag weiterverarbeiten; erwartet: Auftrag enthält die Positionen mit Referenz auf das Angebot (OriginReceiptI3D).
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SyRS-005, SyRS-006, SyRS-007, SyRS-010, SyRS-011, SyRS-012, SyRS-013, SyRS-014, SyRS-015, SyRS-053
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Automatisierte wiederkehrende Vertragsabrechnung
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung / Vertragsverwaltung
Vorbedingung: Verträge mit Abrechnungsintervall und Positionen sind angelegt.
Fakt: Es existiert ein Abrechnungszentrum („Vertragsabrechnung"/AutomatedBilling), das aus Verträgen periodisch Rechnungen erzeugt, inkl. Intervall-Multiplikation, Sammelrechnungen und Versand.
Aussage: Das System soll wiederkehrende Leistungen (Wartungs-, Service-, Mietverträge) automatisiert und periodengerecht in Rechnungen überführen, um manuellen Abrechnungsaufwand zu minimieren.
Ergebnis: Je Abrechnungslauf entstehen Rechnungen mit korrektem Leistungszeitraum, die dem Vertrag zugeordnet und versendet/gedruckt werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs (CreateInvoiceToContractComplete, Zeile 1699) – Begründung: vollständiger Abrechnungsprozess Vertrag→Rechnung implementiert.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/AutomatedBilling/ – Begründung: eigenes UI-Modul „Vertragsabrechnung" belegt den Geschäftsprozess.
- [KONTEXT] docs/reference/receipts/contracts-backend.md – Begründung: beschreibt Billing-Intervalle und automatisierte Abrechnung als Vertragszweck.
Prüfidee: Vertrag mit Monatsintervall und 1 Position abrechnen; erwartet: Rechnung mit Position, Leistungszeitraum = Abrechnungsperiode, Vertragszuordnung gespeichert.
Tracelinks: SyRS-016, SyRS-017, SyRS-019
Konsolidierung: Kandidat: Abrechnungswege Vertragsabrechnung, TimerBilling (StRS-004), Pauschalabrechnung (FlatRateProject) und „Automatische Faktura" überschneiden sich fachlich (Erzeugung von Rechnungen aus Quellobjekten) und sollten im Zielsystem vereinheitlicht werden.
Status: belegt
```
```
ID: StRS-003
Titel: Ticketbasierter Kundenservice mit Eskalation
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Support-Leitung
Vorbedingung: Kunde existiert; Servicemeldung geht ein (Telefon, Mail, Portal).
Fakt: Umfangreiches Helpdesk-Subsystem (52 BL-Klassen) mit Ticket-Entity, konfigurierbaren Status/Prioritäten/Kategorien, Bearbeitern, Fälligkeit, Eskalationslevel und einem 15-minütigen Eskalationsdienst.
Aussage: Das System soll Serviceanfragen als Tickets erfassen, priorisieren, Verantwortlichen zuweisen und bei Überschreitung von Fälligkeiten mehrstufig eskalieren, damit Servicezusagen gegenüber Kunden eingehalten werden.
Ergebnis: Tickets durchlaufen einen kontrollierten Lebenszyklus bis zum Abschluss; Überfälligkeiten lösen Benachrichtigungen aus.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs – Begründung: Ticket-Datenmodell mit DueDate, EscalationLevel, Status, Prioritäten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/Escalation/EscalationBL.cs (DoEscalation) – Begründung: implementierte mehrstufige Eskalation mit Mailversand.
- [KONTEXT] CentronRights.md (Abschnitt Helpdesk) – Begründung: dokumentiert die fachlich gewollten Ticket-Rechte und -Abläufe.
Prüfidee: Ticket mit Priorität und Fälligkeit in der Vergangenheit anlegen; erwartet: Eskalationsdienst erhöht EscalationLevel und versendet Mail an konfigurierte Empfänger.
Tracelinks: SyRS-034, SyRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-004
Titel: Erfassung und Abrechnung von Servicezeiten
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Buchhaltung
Vorbedingung: Ticket existiert.
Fakt: Zeiterfassung erfolgt als Timer am Ticket (Start/Stopp, Pause, abrechenbar-Flag, Abrechnungsartikel, Vertrag-Zuordnung); ein Abrechnungsmodul überführt Timer in Belege und verknüpft sie mit Auftrag/Lieferschein/Rechnung.
Aussage: Das System soll geleistete Servicezeiten tickets- und mitarbeiterbezogen erfassen und wahlweise über Verträge (Kontingente) oder als Einzelleistung fakturieren.
Ergebnis: Erfasste Zeiten sind lückenlos einem Ticket zugeordnet und entweder abgerechnet, in einem Kontingent verbraucht oder als nicht abrechenbar gekennzeichnet.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskTimerArea/HelpdeskTimer.cs – Begründung: Datenmodell mit Calculable, Contract, OrderAssetItemI3D/InvoiceAssetItemI3D (Abrechnungsreferenzen).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (CreateNewReceiptForHelpdekTimers, Zeile 5295) – Begründung: erzeugt Belege aus Ticket-Timern.
- [KONTEXT] Commit baa9e7bd9b „rights check for editing invoice or delivery list date in the settings of timer billing" – Begründung: aktive Weiterentwicklung des Timer-Billing-Prozesses.
Prüfidee: Zwei abrechenbare Timer zu einem Ticket erfassen und über TimerBilling fakturieren; erwartet: Rechnung mit Zeitpositionen, Timer erhalten InvoiceAssetItemI3D.
Tracelinks: SyRS-036, SyRS-037
Konsolidierung: Kandidat: siehe StRS-002 (mehrere Abrechnungswege).
Status: belegt
```
```
ID: StRS-005
Titel: Forderungsmanagement
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung
Vorbedingung: Offene Rechnungen existieren.
Fakt: Module für Mahnung (3 Stufen, Mahnläufe), OPOS, Zahlungseingang und SEPA-Lastschriftexport sind implementiert; Zahlungsziel wird aus Zahlungskonditionen berechnet.
Aussage: Das System soll offene Forderungen überwachen, Zahlungseingänge zuordnen, Lastschriften einziehen und säumige Kunden gestuft mahnen.
Ergebnis: Offene Posten sind jederzeit auswertbar; jede Mahn- und Zahlungsaktion ist protokolliert und rückholbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs (ExecuteDunningRun) – Begründung: implementiertes Mahnwesen mit Stufen und Läufen.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/PaymentTransactions/PaymentTransactionBL.cs – Begründung: SEPA-Export inkl. Rechnungs-Schließung und Rücknahme.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (Module „Mahnung", „OPOS", „SEPA", „Zahlungseingang") – Begründung: eigenständige Module belegen den Geschäftsprozess in der Benutzeroberfläche.
Prüfidee: Überfällige Rechnung mahnen; erwartet: DunningLevel 1 mit Datum/Bearbeiter, Mahnlauf-Nummer vergeben, Mahnschreiben erzeugt.
Tracelinks: SyRS-010, SyRS-020, SyRS-023, SyRS-024
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Übergabe an die Finanzbuchhaltung
Ebene: StRS
Typ: Schnittstelle
Akteur: Buchhaltung, Steuerberater (extern)
Vorbedingung: Abgeschlossene Belege und gepflegte Konten (Kontenrahmen) liegen vor.
Fakt: Export von Personenkonten und Buchungsdaten in DATEV ASCII, DATEV XML Online (2020), Abacus und kundenspezifische Formate; exportierte Belege werden markiert und gegen unbemerkte Änderung geschützt.
Aussage: Das System soll Rechnungs- und Stammdaten periodisch an die Finanzbuchhaltung übergeben, sodass die Buchführung ohne Doppelerfassung erfolgen kann.
Ergebnis: Übergabedateien im Zielformat; übergebene Belege sind als exportiert gekennzeichnet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs – Begründung: implementiert Export von Kunden-/Lieferanten- und Buchungsdaten inkl. Formatwahl.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (HandleIsAlreadyExported, Zeile 8478) – Begründung: erzwingt Rückfrage bei Änderung bereits exportierter Belege.
- [SEKUNDÄR] ModuleRegistration.cs (Module „Buchhaltungsexport/-import", „Datev Belegtransfer", „Kontenrahmen") – Begründung: UI-Module für den Prozess.
Prüfidee: Rechnung exportieren und anschließend neue Version anlegen; erwartet: Dialog „Dieser Beleg wurde bereits an die Buchhaltung übergeben…".
Tracelinks: SyRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Elektronische Rechnungsstellung (ZUGFeRD/XRechnung)
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung, Endkunde/Behörde als Rechnungsempfänger
Vorbedingung: Rechnung ist erstellt; Kunde hat ggf. Leitweg-ID.
Fakt: Eigene ZUGFeRD-Implementierung (InvoiceZugferdBL, Spezifikation 2.1.1 als PDF im Repo), Leitweg-ID-Ermittlung je Kunde, ZUGFeRD-Dateiname als Mailanhang der Vertragsabrechnung.
Aussage: Das System soll Rechnungen zusätzlich als strukturierte E-Rechnung (ZUGFeRD/XRechnung) erzeugen und versenden können, um gesetzliche Anforderungen öffentlicher und privater Empfänger zu erfüllen.
Ergebnis: Zur Rechnung existiert eine standardkonforme XML-/Hybrid-Datei; Behördenempfänger werden über die Leitweg-ID adressiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs – Begründung: Implementierung der ZUGFeRD-Erzeugung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (GetLeitwegID, Zeile 3417; GetLocalZUGFeRDSetting, Zeile 3438) – Begründung: kunden-/belegbezogene E-Rechnungs-Steuerung.
- [KONTEXT] docs/reference/zugferd-field-mapping.md, docs/guides/development/xrechnung.md – Begründung: dokumentierte Feldzuordnung und Normbezug.
Prüfidee: Rechnung mit aktivierter ZUGFeRD-Einstellung versenden; erwartet: Mailanhang mit ZUGFeRD-Datei (Name gemäß GetZugferdFileName).
Tracelinks: SyRS-022
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Bestands-, Beschaffungs- und Fertigungssteuerung
Ebene: StRS
Typ: funktional
Akteur: Lagermitarbeiter, Einkäufer, Fertigung
Vorbedingung: Artikelstamm mit Beständen und Mindestbeständen ist gepflegt.
Fakt: Bestandsführung über Haupt-/Nebenläger mit Bedarfsrechnung (Bestellvorschlag), EK-Fortschreibung beim Wareneingang, Seriennummern-/Barcodeverwaltung, Inventurmodul, Kommissionierung und Produktionsaufträgen.
Aussage: Das System soll Lagerbestände über mehrere Läger führen, Beschaffungsbedarf automatisch ermitteln und Kommissionierung, Inventur sowie einfache Fertigungsaufträge unterstützen.
Ergebnis: Bestände, Bedarf und Seriennummern sind konsistent; Bestellvorschläge decken Unterdeckungen ab.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Purchasing/OrderSuggestionList/OrderSuggestionListBL.cs – Begründung: implementierte Bedarfsformel (Auftragsbedarf + Mindestbestand − Bestand − offene Zugänge).
- [PRIMÄR] src/backend/Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs – Begründung: Bestandsführung und EK-Fortschreibung.
- [SEKUNDÄR] ModuleRegistration.cs (Module „Inventur", „Kommissionierung", „Produktionsaufträge", „Artikelverwaltung") – Begründung: Module belegen die Prozesse.
Prüfidee: Artikel mit Mindestbestand 5 und Bestand 2 anlegen; erwartet: Artikel erscheint im Bestellvorschlag mit Bedarf ≥ 3.
Tracelinks: SyRS-038, SyRS-039, SyRS-040, SyRS-041, SyRS-055
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Einkaufsabwicklung mit Lieferantenbelegkette
Ebene: StRS
Typ: funktional
Akteur: Einkäufer
Vorbedingung: Lieferant ist angelegt.
Fakt: Eigene Lieferantenbelegarten (Bestellung, Wareneingang/Lieferschein, Eingangsrechnung, Lieferantengutschrift) mit eigener Weiterverarbeitungskette und Prüfung doppelter externer Rechnungsnummern.
Aussage: Das System soll den Einkaufsprozess von der Bestellung über den Wareneingang bis zur Eingangsrechnung als Belegkette abbilden und typische Fehler (z. B. doppelt erfasste Lieferantenrechnungen) verhindern.
Ergebnis: Einkaufsbelege sind verkettet; doppelte externe Rechnungsnummern werden erkannt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/SupplierOrders/SupplierOrderSpecificLogic.cs (CanBeForwardedInto → SupplierDeliveryList) und SupplierDeliveryLists/SupplierInvoices/SupplierCreditVouchers-Pendants – Begründung: implementierte Lieferantenkette.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (CheckExternalInvoiceNumberAlreadyUsed, Zeile 4182; GetDuplicateSupplierExternalInvoiceReceiptDescription, Zeile 5095) – Begründung: Dublettenprüfung externer Rechnungsnummern.
- [SEKUNDÄR] UserRightsConst.cs (Klasse Purchase.Supplier mit Offer/Order/DeliveryList/Invoice/CreditVoucher/Contract) – Begründung: Rechtekatalog spiegelt die Einkaufsbelegarten.
Prüfidee: Zwei Eingangsrechnungen mit identischer externer Rechnungsnummer erfassen; erwartet: Warnung/Hinweis auf vorhandenen Beleg.
Tracelinks: SyRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-010
Titel: Zentrale Kunden- und Adressverwaltung mit CRM
Ebene: StRS
Typ: funktional
Akteur: Vertrieb, Service, Buchhaltung
Vorbedingung: —
Fakt: Adressstamm (Accounts) mit Ansprechpartnern, Adressen, Bankverbindungen, kundenindividuellen Konditionen (Zahlungskonditionen je Belegart, Preisliste, Rabatt, Kreditlimit, Mahnparameter) sowie CRM-Aktivitäten, Kampagnen und Umfragen.
Aussage: Das System soll Kunden mit allen vertriebs- und abrechnungsrelevanten Konditionen zentral führen, sodass Belege, Service und Mahnwesen dieselbe Datenbasis nutzen.
Ergebnis: Kundenkonditionen wirken automatisch in allen Prozessen (Belegerstellung, Preisfindung, Mahnwesen).
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs – Begründung: Kundenentity mit PaymentCondition*I3D je Belegart, PriceList, CreditLimit, Dunning-Feldern.
- [SEKUNDÄR] ModuleRegistration.cs (Module „Adressstamm", „CRM", „Kampagnen/Mailing") – Begründung: Module für Pflege und CRM.
- [KONTEXT] README.md („create one in c-entron.NET Adressstamm") – Begründung: Adressstamm als zentrale Anlaufstelle dokumentiert.
Prüfidee: Kunde mit Zahlungskondition „30 Tage" für Rechnungen anlegen und Rechnung erstellen; erwartet: Fälligkeitsdatum = Rechnungsdatum + 30 Tage.
Tracelinks: SyRS-010, SyRS-042
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Artikelstamm und regelbasierte Preisfindung
Ebene: StRS
Typ: funktional
Akteur: Vertrieb, Einkauf, Produktmanagement
Vorbedingung: Artikel sind angelegt oder werden aus Distributorenkatalogen übernommen.
Fakt: Artikelstamm mit 4 Preislisten, Staffelpreisen, Mindestpreis, Listenpreis/EVP, kundenspezifischen Sonderpreisen/Sonderabsprachen, Aktionspreisen und einer Preismatrix mit externen Distributorenquellen; Preisfindung beim Positionseinfügen berücksichtigt Kunde, Vertrag, Menge und Sonderabsprachen.
Aussage: Das System soll Verkaufspreise regelbasiert aus Kundenzuordnung, Vereinbarungen, Menge und aktuellen Einkaufsquellen ermitteln, sodass Positionen ohne manuelle Preisrecherche korrekt bepreist werden.
Ergebnis: Beim Einfügen eines Artikels in einen Beleg werden VK, EK, Rabatt und MwSt automatisch korrekt vorbelegt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptItemBL.cs (UpdateReceiptItemWithArticleInfo, Zeile 3958, Region „Price Calculation") – Begründung: implementierte Preisfindungskaskade.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Warehousing/StockManagement/Article.cs (Price1–4, GetPrice, VolumePrices, MinPrice-Nutzung) – Begründung: Preisdatenmodell.
- [KONTEXT] docs/reference/receipts/actionprice-system.md – Begründung: dokumentiert Preismatrix und Aktionspreise.
Prüfidee: Kunde mit Preisliste 2 und Artikel mit abweichendem Price2 anlegen; erwartet: Belegposition übernimmt Price2 als Basispreis.
Tracelinks: SyRS-009, SyRS-046, SyRS-056
Konsolidierung: Kandidat: Sonderpreise existieren mehrfach (AccountSpecialPrice am Konto, AddressSpecialArticle an der Adresse, SpecialAgreement, Vertragspreise) – im Zielsystem zu einem Preisregelwerk zusammenführen.
Status: belegt
```
```
ID: StRS-012
Titel: Begrenzung des Kreditrisikos
Ebene: StRS
Typ: funktional
Akteur: Vertrieb, Buchhaltung, Geschäftsführung
Vorbedingung: Kunde hat Kreditlimit > 0 und aktive Berechnungsart.
Fakt: Beim Speichern limitrelevanter Belege wird das Kreditlimit gegen die Summe offener Belege (netto oder brutto) geprüft; Überschreitung erzeugt einen Warndialog mit Detailaufstellung und erfordert bewusste Bestätigung.
Aussage: Das System soll verhindern, dass Aufträge das eingeräumte Kreditlimit eines Kunden unbemerkt überschreiten.
Ergebnis: Limitüberschreitungen werden vor dem Speichern angezeigt; das verfügbare Limit wird am Kunden fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (CheckIfCustomerLimitIsReached, Zeile 8636) – Begründung: vollständige Limitprüfung mit Dialogtext „Das Limit von … wurde um … überschritten".
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs (CreditLimit, CreditLimitAvailable, CreditLimitCalculationKind) – Begründung: Datenmodell der Limitsteuerung.
Prüfidee: Kunde mit Limit 1.000 € (brutto) und offenem Auftrag über 900 €; neuen Auftrag über 200 € speichern; erwartet: Warndialog mit Differenz 100 €.
Tracelinks: SyRS-008
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Rollenbasierte Zugriffskontrolle mit Eigentums- und Filialbeschränkung
Ebene: StRS
Typ: Sicherheit
Akteur: Systemadministrator (des Kunden), alle Benutzer
Vorbedingung: Benutzer und Rechtegruppen sind angelegt.
Fakt: Feingranularer Rechtekatalog (UserRightsConst, > 2800 Zeilen) mit Modulen, Aktionen und „einschränkenden Rechten" (nur eigene Objekte, nur eigene Filiale); Prüfungen erfolgen in UI, Modulregistrierung und Business-Logik.
Aussage: Das System soll Funktionen und Datensichten rollenbasiert steuern und dabei auch Einschränkungen auf eigene Objekte bzw. die eigene Filiale durchsetzen.
Ergebnis: Benutzer sehen und bearbeiten nur die Objekte, für die ihre Rechtegruppen sie autorisieren.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs – Begründung: zentraler Rechtekatalog.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs (Zeile 269–291, ShowHelpdeskRight) – Begründung: implementierte Durchsetzung einschränkender Rechte (nur eigene / nur eigene Filiale).
- [KONTEXT] CentronRights.md; docs/guides/development/check-userrights.md – Begründung: dokumentierte Rechtesemantik und Prüfmuster.
Prüfidee: Benutzer mit SHOW_HELPDESK + SHOW_HELPDESK_ONLY_OWN meldet sich an; erwartet: Ticketliste enthält nur Tickets, in denen er Bearbeiter oder Verantwortlicher ist.
Tracelinks: SyRS-029
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: Nachvollziehbarkeit und Revisionsfähigkeit
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Funktionale Eignung/Verlässlichkeit; Compliance-Ziel)
Akteur: Buchhaltung, Wirtschaftsprüfer (mittelbar), Support-Leitung
Vorbedingung: —
Fakt: Belege werden versioniert (Versionstabellen als 1:1-Kopien), jede Belegaktion (Druck, Mail, Storno, Zahlungsmarkierung, EDI) wird im AnlageLog protokolliert; Anlage-/Änderungs-Metadaten (CreatedBy/ChangedBy) sind Tabellenkonvention; Login-IP und Anmeldungen werden gespeichert.
Aussage: Das System soll Änderungen an geschäftskritischen Objekten so aufzeichnen, dass frühere Zustände rekonstruierbar sind und Aktionen einem Benutzer und Zeitpunkt zugeordnet werden können.
Ergebnis: Für jeden Beleg existiert eine lückenlose Versions- und Ereignishistorie.
Belege:
- [PRIMÄR] docs/reference/receipts/receipts-backend-architecture.md i. V. m. Centron.DAO (AssetHeadDAO.SaveAssetVersion, Versionstabellen `*KopfVersions`) – Begründung: implementiertes Versionierungsschema.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptLogBL.cs – Begründung: Protokollierung von Belegereignissen inkl. Benutzer und Zeit.
- [SEKUNDÄR] docs/guides/database/database-conventions.md (CreatedByI3D/ChangedByI3D/IsDeleted) – Begründung: Konvention für Nachvollziehbarkeit auf Datensatzebene.
Prüfidee: Beleg zweimal ändern; erwartet: zwei Einträge in der Versionstabelle mit OriginalI3D-Referenz; ReceiptLog enthält die Aktionen.
Tracelinks: SyRS-006, SyRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Kundenportal-Self-Service
Ebene: StRS
Typ: funktional
Akteur: Endkunde des Systemhauses
Vorbedingung: Endkunde besitzt einen aktiven WebAccount.
Fakt: Blazor-Webanwendung mit Kundenportal-Routen: Tickets (anlegen, Verlauf, Zeiten, Dokumente), Belege einsehen (inkl. PDF-Vorschau, Verträge), Dokumente, Formulare; Portal-Rechte pro WebAccount (nur eigene / alle Anfragen, Kundenadministrator).
Aussage: Das System soll Endkunden einen Web-Zugang bieten, über den sie Tickets eröffnen und verfolgen sowie ihre Belege und Dokumente einsehen können, ohne den Support telefonisch zu kontaktieren.
Ergebnis: Endkunden bedienen Standardanliegen selbstständig; Sichtbarkeit folgt den Portal-Rechten.
Belege:
- [PRIMÄR] src/nexus/CentronNexus (Routen /customerportal/tickets, /customerportal/receipts/…, /customerportal/documents) – Begründung: implementierte Portalfunktionen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs (Zeile 240–266, WebAccountRightsConst-Auswertung) – Begründung: Portal-Sichtbarkeitsrechte durchgesetzt.
Prüfidee: WebAccount mit SHOWONLYOWNREQUESTS meldet sich im Portal an; erwartet: nur selbst gemeldete Tickets sichtbar.
Tracelinks: SyRS-042
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Digitale Angebotsannahme und Signatur
Ebene: StRS
Typ: funktional
Akteur: Endkunde, Vertrieb
Vorbedingung: Beleg wurde als Web-Dokument mit Token-Link bereitgestellt.
Fakt: WebOffer/C-Sign: Belege werden per Token-URL bereitgestellt; Zustände InProcess, AcceptFullWebReceipt, AcceptWebReceiptWithChangeRequests, Rejected, SendToCustomer; Annahme mit/ohne Unterschrift, Änderungswünsche je Position, Ablehnung mit Benachrichtigung des Bearbeiters.
Aussage: Das System soll Kunden ermöglichen, Angebote online einzusehen, anzunehmen (auch rechtsverbindlich mit Unterschrift), Änderungswünsche zu äußern oder abzulehnen, und den Vertrieb über das Ergebnis informieren.
Ergebnis: Der Angebotsstatus ist ohne Medienbruch dokumentiert; angenommene Angebote können direkt weiterverarbeitet werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (ChangeWebReceiptState, Zeile 5903; AcceptWebReceipt/RejectedWebReceipt, Zeilen 6256–6436) – Begründung: implementierter Annahme-/Ablehnungsprozess.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs – Begründung: Statusmodell der Online-Annahme.
- [KONTEXT] Commit 89ccfd650d „Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)" – Begründung: Feature-Zuordnung und Aktualität.
Prüfidee: Angebot per Token öffnen und mit Unterschrift annehmen; erwartet: Status AcceptFullWebReceipt, signiertes PDF archiviert, Bearbeiter benachrichtigt.
Tracelinks: SyRS-044
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: B2B-Webshop (WebCart)
Ebene: StRS
Typ: funktional
Akteur: Endkunde des Systemhauses
Vorbedingung: WebAccount vorhanden; Sonderpreise für den Kunden gepflegt.
Fakt: WebCart-Bereich in Nexus (Shop, Warenkorb, Belegübersicht); Sortiment stammt laut Projekt-README aus den Sonderpreisen des Kunden.
Aussage: Das System soll Endkunden einen Webshop mit ihrem individuell bepreisten Sortiment bieten, aus dem Bestellungen in die Belegverarbeitung des Systemhauses einfließen.
Ergebnis: Bestellungen aus dem Shop erscheinen als Belege beim Systemhaus; Preise entsprechen den Kundenvereinbarungen.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/WebCart (Routen /webcart/shop, /webcart/cart, /webcart/receipts/…) – Begründung: implementierter Shop.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptCartBL.cs (GetSpecialPricesWithArticles, Zeile 228) – Begründung: Sortiment aus AccountSpecialPrice.
- [KONTEXT] README.md Abschnitt „WebCart" – Begründung: dokumentiert Zielgruppe („customers of our customers") und Sonderpreis-Basis.
Prüfidee: Kunde mit 2 Sonderpreisen meldet sich im Shop an; erwartet: genau diese Artikel mit Sonderpreisen sichtbar.
Tracelinks: SyRS-043
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Automatisierter Lieferanten-EDI
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer, Lieferanten/Distributoren
Vorbedingung: EDI-Konfiguration je Lieferant ist hinterlegt.
Fakt: EDI-Downloaddienst (alle 30 Minuten) holt Auftragsbestätigungen, Lieferavis und Rechnungen per FTP/SFTP/FTPS von Distributoren (ALSO, ALSO CH, Alltron, Herweck, Komsa, OpenTrans 2.1) und verarbeitet sie in Belege; Log-Bereinigung nach 185 Tagen.
Aussage: Das System soll Belege der Distributoren automatisch abholen und den Einkaufsbelegen zuordnen, um manuelle Erfassung und Übertragungsfehler zu vermeiden.
Ergebnis: Lieferantenbelege entstehen bzw. aktualisieren sich ohne manuelle Erfassung; Verarbeitung ist protokolliert.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs (Intervall 30 min, Zeile 35–38) – Begründung: implementierter automatischer Abruf.
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/ (SupplierEdiBL.*-Partialklassen) – Begründung: lieferantenspezifische Verarbeitung.
- [KONTEXT] docs/reference/edi/edi-architecture.md, docs/reference/edi/edi-import-rules.md – Begründung: dokumentierte Architektur und Ablauf.
Prüfidee: EDI-Testdatei eines unterstützten Lieferanten bereitstellen; erwartet: Beleg wird importiert, EDI-Log-Eintrag entsteht.
Tracelinks: SyRS-045
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-019
Titel: Lizenzbasierte Steuerung des Funktionsumfangs
Ebene: StRS
Typ: nicht-funktional (Herstellerziel; ISO 25010: Funktionale Eignung)
Akteur: Softwarehersteller, Systemadministrator
Vorbedingung: Lizenzdaten des Kunden liegen vor (Lizenzserver).
Fakt: Lizenzen sind GUIDs mit Count, Gültigkeitsdatum und Maximalversion; Anmeldungen je Anwendung werden gegen Lizenz-Count geprüft; Einzelfeatures (z. B. Eskalationsserver, Passwort-Manager, MyDay-Importe) werden per LicenseManager ein-/ausgeblendet.
Aussage: Das System soll den nutzbaren Funktionsumfang und die Anzahl gleichzeitiger Anmeldungen je Anwendung anhand der erworbenen Lizenzen begrenzen.
Ergebnis: Nicht lizenzierte Funktionen sind nicht nutzbar; Lizenzüberschreitungen verhindern die Anmeldung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs (AuthenticateUser: LicenseManager.CheckLicense vor Ticketvergabe) – Begründung: Lizenzprüfung im Anmeldefluss.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EscalationsService.cs (HasLicense(LicenseGuids.EscalationsServer)) – Begründung: featurebezogene Lizenzprüfung.
- [KONTEXT] docs/reference/security/licensing-system.md – Begründung: dokumentiertes Lizenzmodell.
Prüfidee: Anmeldeversuch, wenn Lizenz-Count erschöpft ist; erwartet: Fehlermeldung, kein Sitzungs-Ticket.
Tracelinks: SyRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Mehrfilial- und Mandantenfähigkeit
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung, Systemadministrator
Vorbedingung: Filialen/Mandanten sind angelegt.
Fakt: Filialen mit eigenen Nummernkreisen, filialbezogene Belege (BranchI3D aus Ersteller oder Betreuer), filialbeschränkende Rechte, „Kalkulation pro Filiale"; Mandantenverwaltung mit eigenen Bankdaten pro Mandant.
Aussage: Das System soll mehrere Filialen (und Mandanten) einer Unternehmensgruppe abbilden, mit getrennten Nummernkreisen, filialbezogener Sichtbarkeit und mandantenbezogenen Zahlungsdaten.
Ergebnis: Belege und Auswertungen sind filial-/mandantenbezogen korrekt getrennt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (UpdateReceiptNumber mit branch-spezifischer NumberGroup, Zeile 7265; GetBranchForNewReceipt, Zeile 7309) – Begründung: filialbezogene Nummern und Filialermittlung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/PaymentTransactions/PaymentTransactionBL.cs (GetMandatorBankInfo über Mitarbeiter→Mandant) – Begründung: mandantenbezogene Bankdaten im Zahlungsverkehr.
- [SEKUNDÄR] ModuleRegistration.cs (Modul „Mandanten", „Kalkulation pro Filiale") – Begründung: eigene Verwaltungsmodule.
Prüfidee: Zwei Filialen mit getrennten Rechnungs-Nummernkreisen; je eine Rechnung erstellen; erwartet: Nummern aus dem jeweiligen Filialkreis.
Tracelinks: SyRS-005, SyRS-029
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-021
Titel: DSGVO-Prozessunterstützung
Ebene: StRS
Typ: funktional
Akteur: Systemhaus (Verantwortlicher), Endkunde
Vorbedingung: AVV-Vorlagen sind gepflegt.
Fakt: DSGVO-Modul mit Auftragsverarbeitungsvertrags-Vorlagen, Online-Bereitstellung von PDF-Dokumenten zur Bestätigung/Unterschrift oder Ablehnung (mit Grund) sowie online bestätigbaren SEPA-Mandaten (Bankname, BIC, IBAN, Unterschrift).
Aussage: Das System soll den Abschluss von Auftragsverarbeitungsverträgen und SEPA-Mandaten digital unterstützen, inklusive Nachweis von Ort, Datum und Unterschrift.
Ergebnis: Bestätigte AVV/SEPA-Dokumente liegen signiert und dem Kunden zugeordnet vor.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Documents/Dsgvo/DsgvoBL.cs (ConfirmOnlinePdfDocument mit signPlace/signDate/signature; DeclineOnlinePdfDocument) – Begründung: implementierter Bestätigungsprozess.
- [SEKUNDÄR] UserRightsConst.cs (Klasse DsgvoModule) – Begründung: eigener Rechtebereich für das DSGVO-Modul.
Prüfidee: AVV-Dokument online bestätigen; erwartet: Signatur, Ort und Datum gespeichert; Dokument dem Kundenkonto zugeordnet.
Tracelinks: SyRS-047
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Auswertungen und Provisionsabrechnung
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung, Vertriebsleitung
Vorbedingung: Bewegungsdaten (Belege, Zeiten, Verträge) liegen vor.
Fakt: Statistik-/Auswertungsmodule (Analytics, Management Info, Vertragsauswertung, Leistungsnachweise, Mitarbeiterauslastung, MSP-Dashboard) sowie Provisionsschemata mit Kundenzuordnung und Provisionsauswertung.
Aussage: Das System soll Führungskennzahlen (Umsatz, Verträge, Auslastung, MSP-Kennzahlen) bereitstellen und Vertriebsprovisionen nach konfigurierbaren Schemata ermitteln.
Ergebnis: Auswertungen sind ohne Datenexport im System abrufbar; Provisionen sind nachvollziehbar berechnet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProvisionSchemaBL.cs, ReceiptProvisionEmployeeGoalBL.cs, ReceiptProvisionEmployeeLevelBL.cs – Begründung: implementierte Provisionslogik.
- [SEKUNDÄR] ModuleRegistration.cs (Module „Analytics", „Management Info", „Provisionsauswertung", „Provisionsschemas verwalten", „Vertragsauswertung", „MSP-Dashboard") – Begründung: Auswertungsmodule.
Prüfidee: Provisionsschema einem Kunden zuordnen und Rechnung fakturieren; erwartet: Provisionsauswertung weist die Rechnung dem Mitarbeiter mit Schema-Satz zu.
Tracelinks: SyRS-053, SyRS-054
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: Ausrichtung auf den deutschsprachigen Markt mit DACH-Besonderheiten
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Funktionale Eignung / Übertragbarkeit)
Akteur: Alle Benutzer, Behörden (AT/CH-Formate)
Vorbedingung: —
Fakt: Deutsch ist Pflichtsprache der UI (dokumentierte „German-First"-Policy, deutsche Basis-RESX, englische .en-RESX); Schweizer Rappenrundung als Einstellung; österreichisches SEPA-Format (STUZZA); Fremdwährungen mit Kursfaktor.
Aussage: Das System soll primär deutschsprachig sein (Englisch als Zweitsprache) und die abrechnungsrelevanten Besonderheiten von Deutschland, Österreich und der Schweiz (Rundung, SEPA-Formate, Währungen) unterstützen.
Ergebnis: UI-Texte und Belege erscheinen deutsch; CH-Belege runden auf 5 Rappen; AT-SEPA-Dateien sind STUZZA-konform.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Helper/ReceiptPriceHelper.cs (0.05-Rundung bei switzerlandRounding) – Begründung: implementierte CH-Rundung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/PaymentTransactions/PaymentTransactionBL.cs (PAIN 008.001.01 STUZZA) – Begründung: AT-Format implementiert.
- [KONTEXT] docs/getting-started/general-structure.md („German-First Language Policy") – Begründung: dokumentierte Sprachpolitik.
Prüfidee: Beleg mit aktivierter CH-Rundung: Bruttosumme 100,02 CHF; erwartet: Rundung auf 100,00 CHF (5-Rappen-Schritt).
Tracelinks: SyRS-012, SyRS-013, SyRS-014, SyRS-049
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: On-Premises-Betrieb beim Systemhaus mit Web-Erweiterung
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit / Betreibbarkeit)
Akteur: Systemadministrator
Vorbedingung: Windows-Server mit MSSQL; optional Linux für den Webservice.
Fakt: Verteilung als Windows-Installer (WixSharp), Webservice als Windows-Dienst/Konsole, dokumentierter Linux-Betrieb, Docker-Images, zentrale XML-Konfiguration (WebServiceConfig.xml) über ein ConnectionManager-Tool, MSSQL als einzige Datenbank.
Aussage: Das System soll beim Kunden (Systemhaus) selbst betrieben werden können: Windows-basierte Installation, zentraler Webservice vor einer MSSQL-Datenbank, konfigurierbar ohne Quellcodeeingriff; die Web-Anwendung ergänzt den Desktop-Client.
Ergebnis: Ein Administrator installiert und konfiguriert das System mit Herstellerwerkzeugen; Web-Clients verbinden sich über den Webservice.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfig.cs – Begründung: zentrale Betriebskonfiguration (DB, TLS, Proxy, 2FA).
- [PRIMÄR] deployment/WixSharpInstaller, src/webservice/Centron.Host.WindowsService, docker/ – Begründung: Installations- und Betriebsartefakte.
- [KONTEXT] docs/guides/services/web-service-on-linux.md – Begründung: dokumentierter Linux-Betrieb.
Prüfidee: Installation per Setup, Konfiguration per ConnectionManager, Start des Dienstes; erwartet: Webservice erreichbar, Clients können sich anmelden.
Tracelinks: SyRS-050, SyRS-051, SyRS-032, SyRS-033, SyRS-052
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Nutzungsbasierte Abrechnung aus RMM-/MSP-Daten
Ebene: StRS
Typ: funktional
Akteur: MSP-Verantwortlicher, Buchhaltung
Vorbedingung: Vertrag ist als RMM-Vertrag konfiguriert; RMM-System (z. B. Riverbird) liefert Nutzungsdaten.
Fakt: Bei der Vertragsabrechnung werden Nutzungsmengen aus dem RMM-System abgerufen und als Positionen eingefügt; bei Nichterreichbarkeit des RMM-Service wird die Rechnungserstellung abgebrochen, um Falschabrechnung zu verhindern; MSP-Collector/-Auswertung aggregieren Kennzahlen.
Aussage: Das System soll verbrauchsabhängige Managed-Services-Leistungen automatisch aus dem Monitoring-System abrechnen und unvollständige Abrechnungen technisch verhindern.
Ergebnis: Rechnungen enthalten die tatsächlichen Nutzungsmengen der Abrechnungsperiode oder werden nicht erstellt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs (CheckRMMArticle, Zeile 721; RMMServiceUnavailableException, Zeile 2414) – Begründung: Abrechnung inkl. Abbruchgarantie implementiert.
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md – Begründung: dokumentierter Fachprozess inkl. Fehlerverhalten.
Prüfidee: Vertragsabrechnung bei abgeschaltetem RMM-Service starten; erwartet: Abbruch mit Meldung „…RMM-Service nicht erreichbar", keine Rechnung.
Tracelinks: SyRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-026
Titel: Sichere Anmeldung und Identitätsintegration
Ebene: StRS
Typ: Sicherheit
Akteur: Alle Benutzer, Systemadministrator
Vorbedingung: Benutzerkonto existiert.
Fakt: Anmeldeverfahren: Benutzername/Passwort, Active Directory, Microsoft Entra ID (OpenID Connect), WebAccounts; optionale Zwei-Faktor-Authentifizierung (RADIUS oder E-Mail-Link) mit konfigurierbarer Gültigkeitsdauer; zeitgesteuerte Kontodeaktivierung; Sitzungs-Tickets mit Ablauf.
Aussage: Das System soll Benutzer sicher authentifizieren, bestehende Unternehmens-Identitäten (AD/Entra ID) integrieren und eine Zwei-Faktor-Absicherung anbieten.
Ergebnis: Nur berechtigte, aktive Benutzer erhalten Sitzungen; 2FA ist je Benutzer erzwingbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/ (BasicAuthenticator, ActiveDirectoryAuthenticator, OpenIdConnectAuthenticator, WebAccountAuthenticator) – Begründung: implementierte Verfahren.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs – Begründung: 2FA-Logik mit Gültigkeitsdauer.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md – Begründung: dokumentierter Entra-ID-Fluss.
Prüfidee: Benutzer mit aktivierter 2FA meldet sich nach Ablauf der Gültigkeitsdauer an; erwartet: zweiter Faktor wird erneut verlangt.
Tracelinks: SyRS-025, SyRS-026, SyRS-027, SyRS-030, SyRS-031, SyRS-032
Konsolidierung: nein
Status: belegt
```
@@ -0,0 +1,79 @@
# Traceability-Matrix
Konsolidierte Forward-/Backward-Traceability über die drei Ebenen. Eine Zeile pro SwRS-Anforderung (unterste Ebene); die Spalten StRS/SyRS zeigen die übergeordnete Kette. SyRS-Anforderungen mit mehreren StRS-Bezügen erscheinen mit ihrem primären StRS-Bezug; vollständige Mehrfachbezüge stehen in den Tracelinks der Einzelanforderungen (StRS.md/SyRS.md/SwRS.md).
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (primär) |
|---|---|---|---|
| StRS-024 | SyRS-032 | SwRS-001 | docs/getting-started/general-structure.md; Centron.BL/BaseBL.cs |
| StRS-024 | SyRS-032 | SwRS-002 | docs/getting-started/general-structure.md (BL/WS-Logic-Muster) |
| StRS-024 | SyRS-032 | SwRS-003 | Centron.BL/Administration/Logins/Auth/Authenticator.cs (Result/MessageCodes) |
| StRS-024 | SyRS-051 | SwRS-004 | docs/guides/database/database-conventions.md |
| StRS-001 | SyRS-001 | SwRS-005 | docs/reference/receipts/receipts-backend-architecture.md („Critical Save Warning"); Centron.DAO/Mappings/TemporaryEntities |
| StRS-001 | SyRS-006 | SwRS-006 | receipts-backend-architecture.md (Versionstabellen); AssetHeadDAO.SaveAssetVersion |
| StRS-001 | SyRS-001 | SwRS-007 | Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs; SpecificLogics.cs |
| StRS-001 | SyRS-002 | SwRS-008 | Centron.Interfaces/Sales/Receipts/ReceiptState.cs |
| StRS-001 | SyRS-003 | SwRS-009 | */[Typ]SpecificLogic.cs (CanBeForwardedInto) |
| StRS-001 | SyRS-003 | SwRS-010 | ReceiptBL.cs ValidateReceiptForwarding (Z. 2462) |
| StRS-001 | SyRS-005 | SwRS-011 | ReceiptBL.cs UpdateReceiptNumber (Z. 7265) |
| StRS-001 | SyRS-007 | SwRS-012 | ReceiptBL.cs CreateLock/RemoveLock (Z. 3160–3175) |
| StRS-001 | SyRS-006 | SwRS-013 | ReceiptBL.cs CreateNewVersion (Z. 3068) |
| StRS-012 | SyRS-008 | SwRS-014 | ReceiptBL.cs CheckIfCustomerLimitIsReached (Z. 8636) |
| StRS-011 | SyRS-009 | SwRS-015 | ReceiptBL.cs CheckArticleMinPrices (Z. 9036) |
| StRS-005 | SyRS-010 | SwRS-016 | ReceiptBL.cs UpdatePaymentDueDate (Z. 8189) |
| StRS-001 | SyRS-011 | SwRS-017 | ReceiptBL.cs UpdateReceiptStateFromPaymentCondition (Z. 8336) |
| StRS-023 | SyRS-012 | SwRS-018 | ReceiptBL.cs UpdateCurrencyFactor (Z. 8359) |
| StRS-023 | SyRS-013 | SwRS-019 | Centron.WebServices.Core/Helper/ReceiptPriceHelper.cs |
| StRS-001 | SyRS-014 | SwRS-020 | ReceiptItemBL.cs (Z. 4088–4098, Steuersatz-Stichtag) |
| StRS-001 | SyRS-015 | SwRS-021 | ReceiptBL.cs SaveReceipt-Pipeline (Z. 3535 ff.) |
| StRS-013 | SyRS-029 | SwRS-022 | ReceiptBL.cs UpdateArticlePositions…Right… (Z. 8030) |
| StRS-009 | SyRS-004 | SwRS-023 | ReceiptBL.cs CheckExternalInvoiceNumberAlreadyUsed (Z. 4182) |
| StRS-001 | SyRS-001 | SwRS-024 | ReceiptItemBL.cs (Positions-Erzeuger, Z. 157–1832) |
| StRS-001 | SyRS-001 | SwRS-025 | ReceiptBL.cs EnsureReceiptDirectoryExists (Z. 9765) |
| StRS-002 | SyRS-016 | SwRS-026 | Centron.Entities/.../ContractLists/ReceiptContract.cs |
| StRS-002 | SyRS-016 | SwRS-027 | AutomaticFacturaWebServiceBL.cs CreateInvoiceToContractComplete (Z. 1699) |
| StRS-002 | SyRS-017 | SwRS-028 | AutomaticFacturaBL.Contracts.cs (Zählerlogik) |
| StRS-025 | SyRS-018 | SwRS-029 | AutomaticFacturaWebServiceBL.cs CheckRMMArticle (Z. 721) |
| StRS-002 | SyRS-019 | SwRS-030 | AutomaticFacturaBL.cs CreateSpecialArticleToContract (Z. 149) |
| StRS-005 | SyRS-020 | SwRS-031 | DunningRunBL.cs UpdateInvoice/SaveDunningRun (Z. 248/277) |
| StRS-006 | SyRS-021 | SwRS-032 | BookKeepingExportBL.cs (Formate, IsReceiptExported) |
| StRS-007 | SyRS-022 | SwRS-033 | InvoiceZugferdBL.cs; docs/reference/zugferd-field-mapping.md |
| StRS-005 | SyRS-023 | SwRS-034 | PaymentTransactionBL.cs InvoiceExportDone/Reset… (Z. 233/296) |
| StRS-026 | SyRS-025 | SwRS-035 | BasicAuthenticator.cs (SHA1, TODO-Salz-Kommentar) |
| StRS-026 | SyRS-026 | SwRS-036 | TwoFactorAuthBL.cs HasToValidateTwoFactor (Z. 82) |
| StRS-026 | SyRS-027 | SwRS-037 | TicketBL.cs (Ablauf 30 min, Salt, Refresh) |
| StRS-019 | SyRS-028 | SwRS-038 | Authenticator.cs GetTicket; docs/reference/security/licensing-system.md |
| StRS-013 | SyRS-029 | SwRS-039 | docs/guides/development/check-userrights.md; HelpdeskBL.cs (Z. 276) |
| StRS-026 | SyRS-030 | SwRS-040 | Authenticator.cs ValidateAppUser (Z. 157–218) |
| StRS-026 | SyRS-031 | SwRS-041 | AccessTokenBL.cs (SHA-256, Protokolle) |
| StRS-024 | SyRS-032 | SwRS-042 | Centron.Host/Services + AspNetCore (Swagger, WCF-Bridge, SignalR) |
| StRS-024 | SyRS-033 | SwRS-043 | Centron.Host/AspNetCore/HostedServices (36 Dienste) |
| StRS-003 | SyRS-034 | SwRS-044 | Centron.Entities/.../Support/Helpdesk.cs; EscalationBL.cs (hlpdsk_requests) |
| StRS-003 | SyRS-035 | SwRS-045 | EscalationBL.cs DoEscalation (Z. 223) |
| StRS-004 | SyRS-036/037 | SwRS-046 | HelpdeskTimer.cs; ReceiptBL.cs CreateNewReceiptForHelpdekTimers (Z. 5295) |
| StRS-008 | SyRS-038 | SwRS-047 | ArticleStockBL.cs; Article.cs (SecondaryStocks) |
| StRS-008 | SyRS-039 | SwRS-048 | ArticleStockBL.cs UpdateArticlePurchasePrice (Z. 74) |
| StRS-008 | SyRS-040 | SwRS-049 | ReceiptItemBL.cs (Z. 4002); ReceiptBL.cs (Z. 3106); BarcodeBL.cs |
| StRS-008 | SyRS-041 | SwRS-050 | OrderSuggestionListBL.cs (Bedarfs-SQL, Z. 89 ff.) |
| StRS-015 | SyRS-042 | SwRS-051 | CentronNexus.Host/appsettings.json; Nexus-Routen |
| StRS-017 | SyRS-043 | SwRS-052 | ReceiptCartBL.cs (Z. 228); README.md WebCart |
| StRS-016 | SyRS-044 | SwRS-053 | ReceiptBL.cs ChangeWebReceiptState (Z. 5903); WebReceiptState.cs |
| StRS-018 | SyRS-045 | SwRS-054 | SupplierEdiBL.*-Partialklassen; EdiDownloadService.cs |
| StRS-011 | SyRS-046 | SwRS-055 | ActionPriceBL.cs; docs/reference/receipts/actionprice-system.md |
| StRS-021 | SyRS-047 | SwRS-056 | DsgvoBL.cs ConfirmOnlinePdfDocument (Z. 182) |
| StRS-014 | SyRS-048 | SwRS-057 | ReceiptLogBL.cs; ChangeTrackingEventListener.cs (ungenutzt) |
| StRS-023 | SyRS-049 | SwRS-058 | LocalizedStrings.resx/.en.resx; general-structure.md |
| StRS-024 | SyRS-050 | SwRS-059 | WebServiceConfig.cs; c-entron.misc.ConnectionManager |
| StRS-024 | SyRS-051 | SwRS-060 | ScriptMethods/Scripts (764 Klassen); create-scripts.md |
| StRS-024 | SyRS-052 | SwRS-061 | CentronMailFactory.cs; developer-security.md |
| StRS-001 | SyRS-053 | SwRS-062 | ReceiptBL.cs CreateFullReportForReceipt (Z. 3221) |
| StRS-022 | SyRS-054 | SwRS-063 | ReceiptProvisionSchemaBL.cs u. a.; UpdateExpiredProvisionSchemasService.cs |
| StRS-008 | SyRS-055 | SwRS-064 | ProductionOrderBL.cs; ProductionOrderOverView.razor |
| StRS-011 | SyRS-056 | SwRS-065 | ReceiptItemBL.cs UpdateReceiptItemWithArticleInfo (Z. 3958) |
| StRS-024 | SyRS-050 | SwRS-066 | global.json; Centron.BL.csproj; version.json; azure/ |
## Abdeckungsübersicht
- **StRS-Ebene:** 26 Anforderungen (StRS-001 … StRS-026); alle mit mindestens einer SyRS-Verfeinerung.
- **SyRS-Ebene:** 56 Anforderungen (SyRS-001 … SyRS-056); alle mit StRS-Aufwärtslink und mindestens einem SwRS-Abwärtslink.
- **SwRS-Ebene:** 66 Anforderungen (SwRS-001 … SwRS-066); alle mit SyRS-Aufwärtslink.
- StRS-Anforderungen mit mehreren SyRS-Kindern (z. B. StRS-001, StRS-008, StRS-026) sind in den jeweiligen `Tracelinks`-Feldern vollständig aufgeführt; diese Tabelle listet je SwRS nur den primären Pfad.
@@ -0,0 +1,201 @@
# Messprotokoll – V1-Fable (solo, `claude-fable-5`, Effort `max`) – Iteration 01, Lauf 23 (Lauf Q)
> **Neue Messreihe mit zwei geänderten Variablen.** Gegenüber allen 21 Vorläufen wechseln
> **gleichzeitig Modell und Effort**: `claude-fable-5` statt Sonnet/Opus, `max` statt `high`.
> Ein Unterschied im Ergebnis lässt sich deshalb **nicht eindeutig** einer der beiden Ursachen
> zuschreiben. Für eine kausale Trennung fehlt der Zwischenpunkt Fable auf `high`.
>
> **Parallelbetrieb:** zwei gleichzeitige Läufe (P, Q). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt.** Tokenverbrauch, Anforderungsanzahl und Denials sind
> unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T21:09:30+02:00
- **Endzeit:** 2026-08-25T21:55:21+02:00
- **Dauer gesamt:** 00:45:51 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:45:49 (`duration_ms`) — API: 00:44:54
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-58d2`
- **Ablage:** `claude-fable-5/solo/max/`
- **Parallele Läufe:** ja – `fable5_solo_v3.6.0-7adf`
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** **`max`** – explizit per `--effort` gesetzt; Gegenprobe im Transkript: 271
Nachrichten, durchgängig `max`. **Erster Block, der vom bisherigen `high` abweicht.**
- **Modell:** `claude-fable-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.193 Input-/17 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 292 |
| Output-Tokens | 215.446 (davon 39.609 Thinking-Tokens) |
| Cache-Write-Tokens | 449.566 |
| Cache-Read-Tokens | 30.404.279 |
| Agent-Turns | 162 |
### Gesamtlauf (`modelUsage`)
| Messgröße | `claude-fable-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 292 | 4.193 | 4.485 |
| Output-Tokens | 215.446 | 17 | 215.463 |
| Cache-Write-Tokens | 449.566 | 0 | 449.566 |
| Cache-Read-Tokens | 30.404.279 | 0 | 30.404.279 |
| Tokens gesamt | 31.069.583 | 4.210 | **31.073.793** |
**Tokens gesamt: 31.073.793** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-fable-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `8ee7b6a1-a203-4eca-a710-f1bf60405551`
- **Permission-Denials:** **0** – —
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 42.674 B | 26 Anforderungen |
| `SyRS.md` | 87.720 B | 56 Anforderungen |
| `SwRS.md` | 97.327 B | 66 Anforderungen |
| `Traceability.md` | 7.202 B | konsolidierte Tabelle |
| `Hypothesen.md` | 13.808 B | Sammlung der `[HYPOTHESE]`-Aussagen |
| `Glossar.md` | 15.807 B | Domänenbegriffe |
| `Analysebericht.md` | 13.651 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **148 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 26 | 17,6 % |
| SyRS | 56 | 37,8 % |
| SwRS | 66 | 44,6 % |
| **Gesamt** | **148** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 78 | 52,7 % |
| Sicherheit | 10 | 6,8 % |
| Schnittstelle | 9 | 6,1 % |
| Daten | 8 | 5,4 % |
| Architektur-Constraint | 5 | 3,4 % |
| funktional / Schnittstelle | 4 | 2,7 % |
| Sicherheit / Daten | 3 | 2,0 % |
| funktional / Sicherheit | 2 | 1,4 % |
| Schnittstelle / funktional | 2 | 1,4 % |
| funktional / nicht-funktional (ISO 25010: Zuverlässigkeit) | 2 | 1,4 % |
| (22 weitere) | 25 | 16,9 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 292 |
| davon `PRIMÄR` | 226 (77,4 %) |
| davon `SEKUNDÄR` | 16 (5,5 %) |
| davon `KONTEXT` | 50 (17,1 %) |
| Belege je Anforderung (Median) | 2,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 148 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 148 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 8 | 5,4 % |
| Konsolidierungskandidaten | 15 | 10,1 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (42 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 148 von 148 mit Tracelinks (100,0 %) |
## Fable-Block (P, Q)
| Messgröße | **Lauf P** | **Lauf Q** |
|---|---:|---:|
| Anforderungen | 207 | 148 |
| — StRS / SyRS / SwRS | 35/84/88 | 26/56/66 |
| Tokens gesamt | 24.225.555 | 31.073.793 |
| Thinking-Tokens | 35.220 | 39.609 |
| Agent-Turns | 152 | 162 |
| Denials / Subagenten | 1 / 0 | 0 / 0 |
## Vergleich der drei Solo-Reihen
| | **Fable, `max`** (2 Läufe) | Opus, `high` (5 Läufe) | Sonnet, `high` (5 Läufe) |
|---|---|---|---|
| Anforderungen | 148 – 207 | 71 – 182 (Median 114) | 42 – 82 (Median 67) |
| Tokens gesamt | 24,22 – 31,07 Mio. | 13,56 – 24,86 Mio. (Median 22,76) | 4,36 – 12,60 Mio. (Median 5,05) |
| Thinking-Tokens | 35.220 – 39.609 | 11.239 – 24.179 | 10.470 – 22.957 |
| Agent-Turns | 152 – 162 | 116 – 195 | 67 – 107 |
## Anmerkungen/Auffälligkeiten
1. **Der höchste Solo-Verbrauch der gesamten Reihe – vom sparsamsten Modell.** Mit 24,22 und
31,07 Mio. Tokens übertrifft der Fable-Block sogar den teuersten Opus-Lauf (24,86 Mio.).
Da Fable als das schnellere und günstigere Modell gilt, ist der plausibelste Treiber der auf
`max` gesetzte Effort – bestätigen lässt sich das aus diesen Daten jedoch **nicht**, weil
Modell und Effort gleichzeitig gewechselt wurden.
2. **Deutlichster Hinweis auf den Effort: die Thinking-Tokens.** Mit 35.220 und 39.609 liegen
sie über allen 21 Vorläufen – der bisherige Höchstwert lag bei 24.179 (Opus, `high`), der
Sonnet-Solo-Median bei rund 12.000. Thinking-Tokens sind die unmittelbarste Wirkung der
Effort-Stufe, und sie steigen hier um Faktor 1,5 bis 3 gegenüber `high`. Das stützt die
Vermutung aus Anmerkung 1, ersetzt aber den fehlenden Kontrollpunkt nicht.
3. **Hohe Ausbeute bei den Anforderungen.** 148 und 207 Anforderungen liegen über dem
Opus-Median (114) und weit über dem Sonnet-Median (67) – bei einem Modell, das von den dreien
das schwächste ist. Die Anforderungsanzahl misst allerdings nur Menge, nicht Belegqualität;
eine inhaltliche Bewertung steht aus.
4. **Konsistent über beide Läufe.** Anforderungen 148 gegenüber 207 (Faktor 1,4), Tokens 24,22
gegenüber 31,07 Mio. (Faktor 1,3), Turns 152 gegenüber 162. Bei nur zwei Messpunkten ist das
keine belastbare Streuungsaussage, fügt sich aber in das Bild der übrigen Solo-Reihen ein,
die alle unter Faktor 3 bleiben.
5. **Was zur kausalen Trennung fehlt:** ein Fable-Block auf `high`. Er würde zeigen, ob der
Sprung im Verbrauch vom Modell oder vom Effort kommt. Alternativ ein Sonnet- oder Opus-Block
auf `max` – dann ließe sich der Effort-Effekt bei bekanntem Modell isolieren.
6. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2693800,"num_turns":162,"stop_reason":"end_turn","session_id":"8ee7b6a1-a203-4eca-a710-f1bf60405551","total_cost_usd":50.17509700000001,"usage":{"input_tokens":292,"cache_creation_input_tokens":449566,"cache_read_input_tokens":30404279,"output_tokens":215446,"output_tokens_details":{"thinking_tokens":39609},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":449566,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1863,"cache_read_input_tokens":469657,"cache_creation_input_tokens":849,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":849},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4193,"outputTokens":17,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004278,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-fable-5":{"inputTokens":292,"outputTokens":215446,"cacheReadInputTokens":30404279,"cacheCreationInputTokens":449566,"webSearchRequests":0,"costUSD":50.17081900000001,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-fable-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Der Lauf ist abgeschlossen. Alle sieben Ergebnisdateien liegen im vorgegebenen Verzeichnis `…\\01_Lauf_2026-08-25_210904_fable5_solo_v3.6.0-58d2\\Ergebnisse\\`, die analysierte Codebasis blieb unverändert (git status leer).\n\n**Ergebnis in Zahlen:**\n\n| Artefakt | Inhalt |\n|---|---|\n| StRS.md | 26 Stakeholder-Anforderungen (Geschäftsziele, 11 Stakeholder-Rollen) |\n| SyRS.md | 56 System-Anforderungen (Belegwesen, Abrechnung, Sicherheit, Schnittstellen, Betrieb; NFRs nach ISO 25010 zugeordnet) |\n| SwRS.md | 66 Software-Anforderungen (Komponenten, Datenmodelle, Algorithmen mit Zeilenangaben) |\n| Traceability.md | Durchgängige Matrix StRS→SyRS→SwRS, eine Zeile je SwRS mit Artefaktbeleg |\n| Hypothesen.md | 18 explizit gekennzeichnete Hypothesen mit offener Frage und Klärungsweg |\n| Glossar.md | ~70 Domänenbegriffe mit Artefaktquellen |\n| Analysebericht.md | Vorgehen, Modulabdeckung, Konsistenzcheck, Selbstbewertung |\n\n**Wesentliche inhaltliche Befunde:** Die Kern-Wertschöpfung (Belegkette Angebot→Rechnung mit vollständiger Speicher-Validierungspipeline, Vertrags-/Zähler-/RMM-Abrechnung, Mahnwesen, SEPA in 5 PAIN-Formaten, DATEV-Export, Preisfindungskaskade, Rechte-/Lizenz-/2FA-Modell) ist durchgängig mit PRIMÄR-Belegen spezifiziert. Acht Anforderungen tragen den Status `belegt; Workaround` als priorisierte Migrationspunkte — darunter ungesalzene SHA-1-Passwörter (mit TODO-Kommentar im Code), der doppelte Persistenzpfad über TemporaryEntities in deutsche Legacy-Tabellen, die dokumentierte Client-Trust-Lücke bei Preisrechten für Neubelege und die nie aktivierte Feld-Audit-Infrastruktur.\n\n**Konsistenzcheck (automatisiert, dokumentiert im Analysebericht):** keine ID-Duplikate, keine Anforderung ohne Beleg, keine toten Tracelinks, alle 13 Formatfelder in allen 148 Anforderungen vollständig, alle Sicherheits-/Abrechnungsanforderungen mit PRIMÄR-Beleg. Fünf Tracelink-Asymmetrien wurden während der Erstellung gefunden und vor dem Finalcheck korrigiert.\n\n**Grenzen (im Bericht offengelegt):** Randmodule wie TAPI, Exchange-Sync, MailScanner, RMA-Details und die Statistik-Kennzahlformeln sind nur strukturell bzw. gar nicht erfasst und als Kandidaten für Folge-Iterationen benannt; risikopriorisiert sind die Klärungen zu Kasse/TSE, GoBD und der Preisrechte-Lücke (H-01, H-02, H-06).\n\nFalls du die Spezifikation zusätzlich als teilbare Webseite (Artifact) haben möchtest, sag kurz Bescheid — ich habe darauf verzichtet, um die Baseline „nur Dateien im Ausgabeverzeichnis\" nicht zu verfälschen.","ttft_ms":14383,"ttft_stream_ms":1920,"time_to_request_ms":48,"type":"result","duration_ms":2749461,"uuid":"f696c90a-3905-44fb-8c87-9715bc7b3905","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 26 | 17,6 % |
| SyRS | 56 | 37,8 % |
| SwRS | 66 | 44,6 % |
| **Gesamt** | **148** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 78 | 52,7 % |
| Sicherheit | 10 | 6,8 % |
| Schnittstelle | 9 | 6,1 % |
| Daten | 8 | 5,4 % |
| Architektur-Constraint | 5 | 3,4 % |
| funktional / Schnittstelle | 4 | 2,7 % |
| Sicherheit / Daten | 3 | 2,0 % |
| funktional / Sicherheit | 2 | 1,4 % |
| Schnittstelle / funktional | 2 | 1,4 % |
| funktional / nicht-funktional (ISO 25010: Zuverlässigkeit) | 2 | 1,4 % |
| (22 weitere) | 25 | 16,9 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 292 |
| davon `PRIMÄR` | 226 (77,4 %) |
| davon `SEKUNDÄR` | 16 (5,5 %) |
| davon `KONTEXT` | 50 (17,1 %) |
| Belege je Anforderung (Median) | 2,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 148 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 148 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 8 | 5,4 % |
| Konsolidierungskandidaten | 15 | 10,1 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (42 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 148 von 148 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_210904_fable5_solo_v3.6.0-58d2\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T21:55:21.3589944+02:00
@@ -0,0 +1 @@
2026-08-25T21:09:30.2840156+02:00
@@ -0,0 +1,382 @@
# Analysebericht
**System:** c-entron ERP-Suite (NEXOWARE c-entron ERP)
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse ohne Ausführung
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha` (`version.json`)
**Datum:** 2026-08-25
**Werkzeuge:** Dateisystem- und Volltextsuche, Quelltextlesung, `git log`. Keine Ausführung, keine
Datenbankverbindung, keine Agenten, keine MCP-Server.
---
## 1. Untersuchungsgegenstand und Vorgehen
### 1.1 Scope
Vorgegeben war die **gesamte Codebasis** ohne Modulbeschränkung. Der tatsächliche Umfang:
| Kennzahl | Wert |
|---|---|
| Projekte in `Centron.sln` | 44 |
| C#-Dateien (`.cs`) | 16 063 |
| XAML-Dateien | 1 233 |
| Razor-Komponenten | 491 |
| Ressourcendateien (`.resx`) | 14 (7 Sprachpaare) |
| Datenbank-Migrationsskripte (C#-Klassen) | 799 (Nummern bis 11820) |
| Markdown-Dokumentation unter `docs/` | 50 Dateien |
| Commits in der Historie | 52 135 |
| `.sql`-Dateien im Repository | 0 (Schema entsteht ausschließlich über Migrationsskripte) |
Bei diesem Umfang ist eine vollständige Zeile-für-Zeile-Analyse in einem Lauf ausgeschlossen. Die
Analysetiefe wurde daher **risikobasiert** priorisiert, entsprechend der Vorgabe des Auftrags:
Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen zuerst.
### 1.2 Durchlaufene Schritte der RRE-Methodenkette
| Schritt | Bearbeitung in diesem Lauf |
|---|---|
| 1 Scope | vorgegeben (gesamte Codebasis) |
| 2 Artefakterhebung | durchgeführt: Quellcode, Konfiguration (`nlog.config`, `appsettings.json`, `Directory.Build.props`, `version.json`, `global.json`), Ressourcen, Deployment (`docker/`, `deployment/`, `azure/`, `.github/workflows/`), Dokumentation (`docs/`, `README.md`, `CentronRights.md`), Change-Historie (`git log`) |
| 3 Technische Analyse | durchgeführt: Projektstruktur, Modulgliederung, Statusmaschinen (Beleg, Mahnstufe), Validierungs- und Berechtigungslogik, Persistenzpfade |
| 4 Semantische Interpretation | durchgeführt: Feld `Fakt` (Beobachtung) getrennt vom Feld `Aussage` (fachliche Soll-Aussage) |
| 5 Formalisierung | durchgeführt: 71 Anforderungen im vorgegebenen Format |
| 6 Traceability-Anreicherung | durchgeführt: 277 Artefaktbelege, Traceability-Matrix mit Vorwärts- und Rückwärtsabdeckung |
| 7 Validierung | **nicht** Teil dieses Laufs (manuell durch Fachexperten) |
---
## 2. Ergebnisumfang
| Ebene | Anforderungen |
|---|---|
| StRS | 15 |
| SyRS | 32 |
| SwRS | 24 |
| **Summe** | **71** |
### Belegverteilung
| Belegklasse | StRS | SyRS | SwRS | Summe | Anteil |
|---|---|---|---|---|---|
| `PRIMÄR` | 33 | 86 | 55 | 174 | 62,8 % |
| `SEKUNDÄR` | 14 | 25 | 22 | 61 | 22,0 % |
| `KONTEXT` | 13 | 17 | 12 | 42 | 15,2 % |
| **Summe** | 60 | 128 | 89 | **277** | 100 % |
Durchschnittlich 3,9 Belege je Anforderung. **Jede der 71 Anforderungen trägt mindestens einen
`PRIMÄR`-Beleg**; die für Sicherheit, Fakturierung und Berechtigungen verschärfte Evidenzanforderung ist
damit für alle betroffenen Anforderungen erfüllt.
### Statusverteilung
| Status | Anzahl |
|---|---|
| `belegt` | 53 |
| `belegt; Workaround` | 18 |
| `HYPOTHESE` | 0 |
Die 18 als `Workaround` markierten Anforderungen beschreiben erkennbare historische Sonderfälle oder
technische Altlasten (u. a. ungesalzene Kennworthashes, doppelter Persistenzpfad, dreifache
Intervallumrechnung, externe Skriptnummernvergabe) und sind bei der Validierung vorrangig zu prüfen.
---
## 3. Modul- und Komponentenübersicht mit Analysetiefe
Legende der Tiefenstufen:
**A = tief** (Kernquelltexte gelesen, Regeln zeilenscharf belegt) ·
**B = mittel** (Schlüsselstellen gelesen, Struktur und Statusmaschinen erfasst) ·
**C = flach** (Struktur, Namensgebung, Enums, Dateiinventar erfasst) ·
**D = nicht analysiert**
### 3.1 Backend (`src/backend/`)
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Administration/Rights` (`AppRightsBL`) | **A** | vollständig gelesen (859 Zeilen); Rechtemodell, Gruppenschutz, Protokollierung, Cache |
| `Administration/Logins/Auth` | **A** | `Authenticator`, `BasicAuthenticator`, `AuthenticatorFactory`, `WebAccountAuthenticator` vollständig gelesen |
| `Administration/Logins` (`TicketBL`, `WebAccountBL`) | **A** | `TicketBL` vollständig; `WebAccountBL` Anmeldepfad |
| `Administration/Logins/TwoFactor` | **B** | `TwoFactorAuthBL` Entscheidungslogik gelesen; Validatoren nur inventarisiert |
| `Administration/Licensing` (`LicenseManager`) | **A** | vollständig gelesen (412 Zeilen) |
| `Administration/AccessTokens` | **B** | Validierung, Erzeugung, Hashing, Lizenzbegrenzung gelesen |
| `Administration/Company` (`NumberGroupBL`) | **A** | vollständig gelesen |
| `Administration/Scripts` (`ScriptEngineBL`) | **B** | Engine bis Z. 130 gelesen; 2 von 799 Skripten stichprobenartig |
| `Administration/DataSecurity`, `.../Documents/Dsgvo` | **B** | Rechteprüfung, Statistikermittlung, Vertragsverwaltung gelesen |
| `Administration/Settings` | **C** | über Nutzungsstellen und Dokumentation erschlossen |
| `Sales/Receipts` (`ReceiptBL`, 11 441 Zeilen) | **B** | gezielt gelesen: Statusübergänge, Rechteprüfmethoden, ZUGFeRD-Bedingung, Protokollierung, Nummernkreis. Ca. 15 % des Umfangs |
| `Sales/Receipts/Invoices/InvoiceSpecificLogic` | **A** | vollständig gelesen (803 Zeilen) |
| `Sales/Receipts/Invoices/Dunning` | **B** | Statusmaschine, Lauf und Rücknahme gelesen |
| `Sales/CustomerAssets/AutomaticFactura` (6 101 Zeilen) | **B** | Intervallumrechnung, Kontingentbuchung, Intervallbeginn gelesen. Ca. 10 % |
| `Sales/Support` (Helpdesk, ca. 50 Klassen) | **B** | `HelpdeskCloseBL`, `HelpdeskTimerBL`, `UpdateHelpdeskBL` (Ausschnitte) |
| `Sales/Customers`, `Accounts`, `BusinessPartner` | **C** | Struktur erfasst |
| `Warehousing` (Artikel, Lager, Barcode, Preise) | **C** | Struktur und Klassennamen erfasst |
| `EDI` (8 Lieferantenformate) | **C** | Enums und Verzeichnisstruktur erfasst; keine Parserlogik gelesen |
| `Finances`, `Accounting` | **C** | Struktur erfasst |
| `Centron.Entities` (`ReceiptBase`, Basisklassen) | **B** | Belegbasis und Schlüsselkonventionen gelesen |
| `Centron.DAO` (Mappings) | **B** | Beispielhaft `RechKopfMaps`, `ReceiptInvoiceMaps`, `ReceiptInvoiceVersionMaps`, `CentronChecklistBaseMaps` |
| `Centron.Interfaces` (Enums, Results, CalculationUtils) | **A** | `CentronObjectKindNumeric`, `ReceiptState`, `ApplicationKind`, `BillingIntervalKinds`, `EdiDataType`, `EDILogState`, `DefaultMessageCodes`, `ResultStatus`, `CalculationUtils` vollständig |
| `Centron.BL` - übrige ca. 60 Fachbereiche | **D** | siehe Abschnitt 5 |
### 3.2 Web-Service (`src/webservice/`)
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Centron.Host` Interception (`AuthenticateInterceptor`) | **A** | vollständig gelesen |
| `Centron.Controllers` Autorisierungsattribute | **C** | Dateiinventar; Inhalte nicht gelesen |
| `Centron.Controllers` REST-Controller (ca. 40) | **C** | Inventar erfasst |
| `Centron.WebServices.Core` (2 530 Dateien, DTOs) | **C** | gezielt: `UserRightsConst`, EDI-Enums, `LoginRequest` |
| `Centron.Host.WindowsService` / `.Console` | **B** | Konfigurationen gelesen |
### 3.3 Clients
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Centron.WPF.UI` (5 255 Dateien) | **C** | `ModuleRegistration.cs` (84 Module) und Modulverzeichnisstruktur; keine ViewModels gelesen |
| `CentronNexus` (762 Dateien, 460 Razor) | **C** | Bereichsstruktur (WebCart, WebOffer, ServiceBoard, DocumentSigning, Management); keine Komponenten gelesen |
| `CentronNexus.OutlookAddIn` | **D** | nur Existenz erfasst |
| `Centron.Controls` (880 Dateien) | **D** | nur Existenz und Ressourcen erfasst |
### 3.4 Querschnitt
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| Build/Versionierung (`Directory.Build.props`, `version.json`, `global.json`) | **A** | vollständig gelesen |
| Deployment (`docker/`, `deployment/`) | **B** | `Dockerfile`, `appsettings.json` gelesen; WixSharp-Installer nur inventarisiert |
| CI/CD (`.github/workflows/`, `azure/`) | **C** | `tests.yml` und `build.yml` (Kopfteile) gelesen |
| Protokollierung (`nlog.config` × 3, `appsettings.json`) | **A** | Windows-Dienst-Konfiguration vollständig |
| Tests (`tests/`, 12 Projekte) | **C** | Inventar und CI-Matrix erfasst; keine Testfälle gelesen |
| Externe Konnektoren (`src/apis/`: GLS, Shipcloud, eBInterface, ITscope, Icecat, FinAPI, COP, EGIS) | **C** | Inventar erfasst |
| Change-Historie | **B** | `git log` der letzten 200 Commits ausgewertet; Ticketreferenzen als `KONTEXT`-Belege verwendet |
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde nach Fertigstellung der drei Spezifikationsdokumente maschinell über die erzeugten
Dateien ausgeführt.
### 4.1 Doppelte oder mehrfach vergebene IDs
**Ergebnis: keine Befunde.**
| Datei | Anforderungen | Doppelte IDs |
|---|---|---|
| `StRS.md` | 15 | 0 |
| `SyRS.md` | 32 | 0 |
| `SwRS.md` | 24 | 0 |
Die IDs sind je Ebene lückenlos fortlaufend (StRS-001…015, SyRS-001…032, SwRS-001…024).
### 4.2 Anforderungen ohne Beleg
**Ergebnis: keine Befunde.** Alle 71 Anforderungen führen mindestens einen Beleg, und alle 71 führen
mindestens einen `PRIMÄR`-Beleg. Die verschärfte Evidenzanforderung für Sicherheit, Fakturierung und
Berechtigungen ist damit erfüllt; keine Anforderung musste deswegen als `[HYPOTHESE]` markiert werden.
### 4.3 Tracelinks auf nicht existierende IDs
**Ergebnis: keine Befunde.** 67 eindeutige IDs werden in den `Tracelinks`-Feldern referenziert; alle 67
sind definiert. Es existiert kein Verweis ins Leere.
**Nebenbefund - asymmetrische Verweise:** Vier SwRS-IDs werden in den `Tracelinks`-Feldern der
SyRS-Anforderungen nicht genannt, obwohl sie ihrerseits auf eine SyRS-Anforderung verweisen:
| SwRS-ID | verweist auf | wird von dort nicht zurückverwiesen |
|---|---|---|
| SwRS-004 (Zweischichtiges DB-Schema) | SyRS-001, SyRS-026 | ja |
| SwRS-006 (Schlüsselkonvention I3D) | SyRS-001 | ja |
| SwRS-018 (Modulregistrierung) | SyRS-006, SyRS-014, SyRS-032 | ja |
| SwRS-019 (Einstellungsverwaltung) | SyRS-016, SyRS-024 | ja |
Weitere Asymmetrien betreffen SwRS-002 → SyRS-006, SwRS-003 → SyRS-001, SwRS-007 → SyRS-026,
SwRS-012 → SyRS-024 und SwRS-013 → SyRS-003.
**Behandlung:** In `Traceability.md` wurde die **symmetrische Hülle** beider Richtungen gebildet und als
maßgebliche Relation ausgewiesen. Die Rückwärts-Traceability (SwRS → SyRS → StRS) ist damit lückenlos, die
Vorwärts-Traceability (StRS → SyRS → SwRS) über die Abdeckungsmatrizen in `Traceability.md`,
Abschnitte 2 und 3, ebenfalls. Fachlich ist keine Anforderung unverbunden.
### 4.4 Vollständigkeit der Pflichtfelder
**Ergebnis: keine Befunde.** Alle zwölf Pflichtfelder (`Titel`, `Ebene`, `Typ`, `Akteur`,
`Vorbedingung`, `Fakt`, `Aussage`, `Ergebnis`, `Prüfidee`, `Tracelinks`, `Konsolidierung`, `Status`) sind
in allen 71 Anforderungen belegt (jeweils 71 Vorkommen).
### 4.5 Abdeckung
- Alle 15 StRS-Anforderungen sind durch mindestens eine SyRS-Anforderung abgedeckt.
- Alle 32 SyRS-Anforderungen sind durch mindestens eine SwRS-Anforderung konkretisiert.
- Alle 24 SwRS-Anforderungen verweisen auf mindestens eine existierende SyRS-Anforderung.
### 4.6 Konsolidierungsbefunde
19 Konsolidierungskandidaten wurden identifiziert und in `Traceability.md`, Abschnitt 5, als
Redundanzregister (K-01…K-19) zusammengefasst. Die gewichtigsten:
| Nr. | Redundanz | Bewertung |
|---|---|---|
| K-08 | Doppelimplementierung jeder Modulschnittstelle (`BL*Logic` / `WS*Logic`) | größte strukturelle Redundanz; entfällt in der Zielarchitektur vollständig |
| K-06 | Belegpersistenz über modernes View-Mapping **und** Legacy-Save-Repository | häufigste Fehlerquelle laut Entwicklerdokumentation |
| K-01 | Vier Mechanismen zur Rechteprüfung | Sicherheitsrelevant: unterschiedliche Cache-Semantik |
| K-02 | Drei Implementierungen der Ticketabschluss-Prüfung, davon eine wirkungslos | Prozessintegrität, siehe H-03 |
| K-03 | Drei Implementierungen der Intervallumrechnung mit abweichender `Daily`-Behandlung | Fakturierungsrelevant, siehe H-02 |
| K-04 | Vier Auslöser für den Belegübergang nach "abgeschlossen" | erschwert eine belastbare Statusmaschine |
| K-07 | Drei Hashverfahren nebeneinander | Sicherheitsrelevant, siehe SwRS-009 |
---
## 5. Bekannte Lücken
| Nr. | Lücke | Auswirkung |
|---|---|---|
| L-01 | **Delphi-Altsystem nicht im Arbeitsverzeichnis.** `LicenseManager.TryFixCentronDelphiVersionNumber()` und der Kommentar in `CentronObjectKindNumeric.cs` belegen ein aktiv genutztes Delphi-System (Version 9.3.x) auf derselben Datenbank und mit derselben Lizenz-GUID. | Fachfunktionen, die ausschließlich dort implementiert sind, fehlen in dieser Spezifikation vollständig. Siehe H-08. |
| L-02 | **Kein Datenbankschema als Artefakt.** Es existieren null `.sql`-Dateien; das Schema entsteht ausschließlich zur Laufzeit aus 799 Migrationsskripten. | Constraints, Indizes, Trigger, Views und Default-Werte konnten nicht als `PRIMÄR`-Belege herangezogen werden. Alle datenbezogenen Anforderungen stützen sich auf Mappings, Konventionen und Skripte. |
| L-03 | **EDI-Verarbeitungslogik nicht gelesen.** Nur Enums und Verzeichnisstruktur erfasst. | Die konkreten Feldzuordnungen, Validierungen und Fehlerbehandlungen je Lieferant fehlen. |
| L-04 | **Oberflächenlogik der Clients nicht gelesen.** 5 255 WPF-Dateien und 460 Razor-Komponenten wurden nur strukturell erfasst. | Validierungen und Pflichtfeldregeln, die ausschließlich in ViewModels bzw. Komponenten implementiert sind, fehlen. |
| L-05 | **Testprojekte nicht ausgewertet.** 12 Testprojekte (BL, DAO, Core, Controls, Integration, End-to-End, Nexus, Playwright, 4 API-Testprojekte). | Tests sind eine hochwertige Quelle für erwartetes Fachverhalten; dieses Potenzial ist ungenutzt. |
| L-06 | **Rechteverwendung nicht analysiert.** 750 Rechtekonstanten; keine Verwendungsanalyse über alle 16 063 Dateien. | Der produktiv relevante Rechteumfang ist unbekannt. Siehe H-11. |
| L-07 | **Fachbereiche ohne jede Anforderung.** Lagerwirtschaft/Inventur, Produktion/PLM, Kassenbuch, Online-Banking/Zahlungsverkehr, CRM-Kampagnen, Projektmanagement, Asset-/Inventarmanagement (Riversuite/DocuBoard), TAPI-Telefonie, Reportengine, Mailscanner/Mailversand, Kalender/Exchange-Synchronisation, Statistik/Dashboards, KI-Chat-Modul, Umfragen, RMA, Provisionsabrechnung, Leasing, Checklistenverwaltung, Task-/Prozessmanagement, Passwortmanager, Videoportal, SEPA/Lastschrift. | Schätzungsweise 55-65 % des Fachumfangs sind nicht spezifiziert. |
| L-08 | **Change-Historie nur stichprobenartig.** 200 von 52 135 Commits ausgewertet. | Historische Begründungen für Sonderfälle blieben weitgehend ungehoben. |
---
## 6. Selbstbewertung
### 6.1 Vollständig analysierte Module
Als **vollständig** (Tiefe A) gelten:
`AppRightsBL`, `Authenticator`/`BasicAuthenticator`/`AuthenticatorFactory`/`WebAccountAuthenticator`,
`TicketBL`, `LicenseManager`, `NumberGroupBL`, `InvoiceSpecificLogic`, `CalculationUtils`,
`AuthenticateInterceptor`, `SHA1Decoder`, `CryptoUtils`, sowie die zentralen Enums und Wertetypen
(`CentronObjectKindNumeric`, `ReceiptState`, `ApplicationKind`, `BillingIntervalKinds`, `EdiDataType`,
`EDILogState`, `DefaultMessageCodes`, `ResultStatus`, `CentronConnectionType`).
Diese Auswahl deckt die vom Auftrag priorisierten Risikobereiche - **Sicherheit, Berechtigungen und die
Kernregeln der Fakturierung** - ab.
### 6.2 Stichprobenhaft analysierte Module
Tiefe B: `ReceiptBL` (ca. 15 %), `AutomaticFacturaBL.Contracts` (ca. 10 %), `DunningBL`/`DunningRunBL`,
`HelpdeskCloseBL`/`HelpdeskTimerBL`/`UpdateHelpdeskBL`, `TwoFactorAuthBL`, `AccessTokenBL`,
`ScriptEngineBL`, `DataSecurityBL`/`DsgvoBL`, DAO-Mappings, Entitätsbasisklassen, Deployment.
### 6.3 Nicht analysierte Module
Siehe L-07. Der Anteil nicht spezifizierter Fachbereiche wird auf 55-65 % geschätzt (Grundlage: 84
registrierte UI-Module gegenüber 15 fachlich abgedeckten Bereichen; ca. 60 BL-Fachverzeichnisse gegenüber
ca. 12 bearbeiteten).
### 6.4 Stellen mit dünner Beleglage
Der `PRIMÄR`-Anteil liegt insgesamt bei 62,8 %. Überdurchschnittlich viele `SEKUNDÄR`- und
`KONTEXT`-Belege - und damit die dünnste Beleglage - weisen auf:
| Anforderung | Beleglage | Ursache |
|---|---|---|
| StRS-015 / SyRS-031 (Betriebsformen) | 2 `PRIMÄR`, 1 `SEKUNDÄR`, 1 `KONTEXT` je Anforderung | Betriebsverhalten ist nur aus Konfiguration ableitbar, nicht aus durchgesetzter Logik |
| SyRS-021 (EDI-Formate) | Enums `PRIMÄR`, Abdeckungsgrad je Lieferant nur `KONTEXT` | Parserlogik nicht gelesen (L-03) |
| StRS-014 / SyRS-028 (Mehrsprachigkeit) | Ressourcendateien `PRIMÄR`, Vollständigkeit nicht geprüft | Kein Abgleich der Schlüsselmengen durchgeführt |
| SwRS-006 / SwRS-007 (Schlüssel- und Auditspalten) | Konventionsdokument als `PRIMÄR` gewertet, Schema selbst nicht prüfbar | L-02 |
| StRS-005 (Helpdesk) | Umfangsargument über Verzeichnisinventar | Nur 3 von ca. 50 Helpdesk-Klassen gelesen |
| StRS-009 (Beschaffung/EDI) | Belegarten `PRIMÄR`, Prozessablauf `KONTEXT` | L-03 |
Methodisch relevant: **Die Entwicklerdokumentation unter `docs/` wurde durchgängig nur als `KONTEXT`
klassifiziert und nie als alleiniger Beleg verwendet.** Der Grund ist ein konkreter Widerspruch zum Code
(`receipts-backend-architecture.md` beschreibt vier Belegzustände, der Code kennt drei) - siehe H-07. Das
hat den `PRIMÄR`-Anteil gesenkt, die Belastbarkeit der Spezifikation aber erhöht.
### 6.5 Was in einer Folge-Iteration nachzuholen ist
Priorisierte Empfehlungen:
**Priorität 1 - Klärung offener Risiken (blockierend für die Zielarchitektur)**
1. **Delphi-Altsystem abgrenzen** (H-08, L-01): ohne diese Klärung ist der Migrationsumfang unbestimmt.
2. **Testprojekte auswerten** (L-05): 12 Testprojekte sind die verlässlichste ungenutzte Quelle für
erwartetes Fachverhalten - insbesondere `Centron.Tests.EndToEnd`, das laut Belegdokumentation die
Datenbankskripte ausführt und Rohtabellenwerte prüft. Erwarteter Nutzen: hoher Zuwachs an
`PRIMÄR`-Belegen bei geringem Aufwand.
3. **Datenbankschema rekonstruieren** (L-02): durch Auswertung aller 799 Migrationsskripte ließe sich das
Zielschema mit Constraints und Indizes ableiten, ohne die Datenbank zu betreiben.
**Priorität 2 - Abdeckung der Fachbreite**
4. **Lagerwirtschaft und Bestandsführung**, **Zahlungsverkehr/Online-Banking**, **Provisionsabrechnung**
und **Kassenbuch** ausarbeiten - alle vier sind abrechnungsrelevant und unterliegen damit derselben
verschärften Evidenzanforderung wie die bereits bearbeiteten Bereiche.
5. **`ReceiptBL` systematisch erschließen** (11 441 Zeilen, bisher ca. 15 %): die verbleibenden 85 %
enthalten mit hoher Wahrscheinlichkeit weitere durchgesetzte Geschäftsregeln.
6. **EDI-Verarbeitung je Lieferant** (L-03) und die **ZUGFeRD-Feldzuordnung** gegen die vorhandenen
Zuordnungsdokumente prüfen.
**Priorität 3 - Methodische Vertiefung**
7. **Rechteverwendungsanalyse** über alle 16 063 Dateien (L-06), um den produktiv relevanten
Rechteumfang zu bestimmen.
8. **Oberflächenvalidierungen** aus ViewModels und Razor-Komponenten heben (L-04) - dort liegen
erfahrungsgemäß Pflichtfeld- und Plausibilitätsregeln, die serverseitig fehlen.
9. **Erweiterte Commit-Analyse** (L-08): gezielte Suche nach Commits zu den 18 als `Workaround`
markierten Stellen, um deren historische Begründung zu belegen.
### 6.6 Bewertung der Ergebnisqualität
**Stärken dieses Laufs**
- Vollständige Belegpflicht eingehalten: 71 von 71 Anforderungen mit `PRIMÄR`-Beleg, keine unbelegte
Soll-Aussage.
- Konsequente Trennung von `Fakt` und `Aussage`, dadurch ist jede Interpretation für den Fachexperten
überprüfbar.
- Konsistenzcheck ohne Befund bei IDs, Belegen und Tracelinks.
- 19 konkrete Konsolidierungskandidaten mit Fundstellen - unmittelbar verwertbar für den
Architekturentwurf des Zielsystems.
- 18 identifizierte Altlasten/Sonderfälle mit Migrationsrelevanz.
**Schwächen dieses Laufs**
- **Die Fachbreite ist die größte Schwäche.** Etwa 55-65 % des Fachumfangs sind nicht spezifiziert. Die
vorliegende Spezifikation ist als Basis für eine Neuimplementierung **noch nicht ausreichend**; sie
deckt Sicherheit, Berechtigungen und den Kern der Belegverarbeitung ab, nicht aber die Fachbreite.
- Der Detaillierungsgrad ist ungleich: `InvoiceSpecificLogic` ist zeilenscharf erfasst, die
gleichrangigen Logiken der übrigen sechs Kundenbelegarten sind es nicht. Das birgt die Gefahr, dass
belegartspezifische Abweichungen unentdeckt bleiben.
- Die Prüfideen sind konzeptionell formuliert und nicht gegen ausführbare Testfälle validiert.
- Nichtfunktionale Anforderungen sind gegenüber funktionalen unterrepräsentiert (5 von 71 explizit einem
ISO/IEC-25010-Merkmal zugeordnet, weitere implizit). Insbesondere zu Performance-Effizienz,
Skalierbarkeit und Lastverhalten liegen kaum Artefaktbelege vor - ein für eine SaaS-Zielarchitektur
wesentlicher blinder Fleck.
**Einschätzung der Reife:** Die Spezifikation ist für die abgedeckten Bereiche belastbar und
validierungsfähig. Für die vollständige Ablösung des Altsystems sind nach heutiger Einschätzung
mindestens drei bis vier weitere Iterationen entlang der Prioritäten in Abschnitt 6.5 erforderlich.
---
## 7. Randbedingungen - Einhaltung
| Vorgabe | Einhaltung |
|---|---|
| Keine Halluzinationen; nicht Belegbares offenlegen | eingehalten - jede Anforderung mit `PRIMÄR`-Beleg; Nicht-Belegbares in `Hypothesen.md` (11 offene Fragen) und Abschnitt 5 (8 Lücken) |
| Keine Generierung von Code | eingehalten - ausschließlich Spezifikationsartefakte erzeugt |
| Keine Annahme nicht vorhandener Tools | eingehalten - ausschließlich Dateisystemsuche, Quelltextlesung und `git log` verwendet |
| Migrationsperspektive (Workarounds kennzeichnen) | eingehalten - 18 Anforderungen mit `Status: belegt; Workaround` |
| Sprache Deutsch, technische Bezeichner im Original | eingehalten |
| Codebasis nur lesen, nicht verändern | eingehalten - siehe Abschnitt 8 |
---
## 8. Nachweis der Unverändertheit der Codebasis
Der Arbeitsbereich `C:\DEV\MasterArbeit\QuellCode\CentronERP` wurde ausschließlich lesend verwendet.
Sämtliche Ergebnisdateien wurden nach
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\Ergebnisse\`
geschrieben. Der Git-Status der Codebasis war zu Beginn des Laufs sauber (`clean`) und wurde nicht durch
schreibende Operationen berührt.
---
## 9. Erzeugte Artefakte
| Datei | Inhalt |
|---|---|
| `StRS.md` | 15 Stakeholder-Anforderungen, Systemüberblick, Stakeholderliste |
| `SyRS.md` | 32 Systemanforderungen (27 funktional, 5 explizit nicht-funktional nach ISO/IEC 25010) |
| `SwRS.md` | 24 Softwareanforderungen (Architektur, Datenmodell, Sicherheitsmechanismen, Berechnungsregeln) |
| `Traceability.md` | Haupttabelle, zwei Abdeckungsmatrizen, Redundanzregister K-01…K-19 |
| `Hypothesen.md` | 11 offene Fragen mit fehlender Information und Priorisierung |
| `Glossar.md` | Domänen- und Systembegriffe mit Fundstellen |
| `Analysebericht.md` | dieses Dokument |
@@ -0,0 +1,404 @@
# Glossar
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
Das Glossar definiert die in `StRS.md`, `SyRS.md` und `SwRS.md` verwendeten Domänen- und Systembegriffe.
Jeder Eintrag nennt die Fundstelle, aus der die Bedeutung abgeleitet wurde. Technische Bezeichner
(Klassen, Methoden, Spalten) sind in ihrer Originalsprache belassen.
---
## A
**Abholschein** (`PickupListClass = 5`, Tabellen `AbholKopf`/`AbholPos`, View `PickupLists`)
Kundenbeleg, mit dem Waren zur Abholung durch den Kunden bereitgestellt werden. Eine der sieben
Kundenbelegarten.
*Beleg:* `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 41-42.
**Access-Token**
Langlebiges, widerrufbares Zugangsmerkmal für den API-Zugriff durch Fremdsysteme, alternativ zum
Sitzungsticket. 48 Zeichen, gespeichert als SHA-256-Hash, optional befristet.
*Beleg:* `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs`.
**AnlageArt**
Numerischer Schlüssel der Belegart in der gemeinsamen Protokolltabelle `AnlageLog`; entspricht den Werten
aus `CentronObjectKindNumeric` (1 = Angebot … 22 = Vertrag).
*Beleg:* `docs/reference/receipts/receipts-backend-architecture.md`, Abschnitt "AnlageArt Values".
**Angebot** (`OfferClass = 1`, Tabellen `AngKopf`/`AngPos`, View `Offers`)
Unverbindliches Leistungsangebot an einen Kunden; Ausgangspunkt der Belegkette.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 23-24.
**AppGroup** (Tabelle `Sichgrup`)
Rechtegruppe. Rechte werden ausschließlich Gruppen zugewiesen, Benutzer erhalten Rechte über die
Gruppenmitgliedschaft. Die Gruppe "Administratoren" (I3D 6) ist gegen Löschung geschützt.
*Beleg:* `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 348-374.
**AppUser** (Tabelle `Sichbenu`)
Mitarbeiterkonto zur Anmeldung am System. Verknüpft mit einem `Employee` (Personalstamm) und über
`AppUserMember` (`Sichmemb`) mit Rechtegruppen.
*Beleg:* `AppRightsBL.cs` Z. 95-111; `Authenticator.cs` Z. 157-218.
**ApplicationKind**
Anmeldefähige Anwendung (z. B. "NEXOWARE c-entron ERP", "c-entron Nexus", "Outlook Add-In",
"Service-Board"). Trägt eine Lizenz-GUID, eine Ablaufart (`ExpirationKind`), eine Nutzungsart
(`LicenseUsageKind`) sowie optional ein erforderliches (`RequiredRight`) und ein ausschließendes Recht
(`DisallowingRight`). 44 Anwendungen sind definiert.
*Beleg:* `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs`.
**Auftrag** (`OrderClass = 2`, Tabellen `AufKopf`/`AufPos`, View `Orders`)
Verbindliche Kundenbestellung; entsteht typischerweise aus einem Angebot.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 25-26.
---
## B
**Beleg** (engl. *Receipt*)
Sammelbegriff für die kaufmännischen Geschäftsobjekte mit Kopf- und Positionsdaten. Unterschieden werden
**Kundenbelege** (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag) und
**Lieferantenbelege** (Anfrage, Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift).
*Beleg:* `CentronObjectKindNumeric.IsCustomerReceipt()` / `IsSupplierReceipt()`.
**Belegkopf** (`*Kopf`)
Kopfdatensatz eines Belegs mit Nummer, Datum, Version, Status, Kunde, Adressen, Währung und Audit-Feldern.
*Beleg:* `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs`.
**Belegposition** (`*Pos`)
Positionsdatensatz eines Belegs mit Artikel, Menge, Preis, Rabatt, Steuersatz und Positionsnummer.
*Beleg:* `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptItemBase.cs`.
**Belegstatus** (`ReceiptState`)
Zustand eines Belegs: `Active` = 1 ("offen"), `Completed` = 2 ("abgeschlossen"), `Canceled` = 3
("storniert").
*Beleg:* `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs`.
**Belegversion** (`*Versions`-Tabellen)
Unveränderlicher Abzug einer früheren Belegfassung (Kopf und Positionen) in einer strukturgleichen
Versionstabelle, referenziert über `OriginalI3D`.
*Beleg:* `src/backend/Centron.DAO/Mappings/Sales/Receipts/Invoices/ReceiptInvoiceVersionMaps.cs`.
**Belegweiterführung** (engl. *forwarding*)
Erzeugung eines Folgebelegs aus einem bestehenden Beleg unter Übernahme von Positionen und Steuersätzen.
Die zulässigen Quell- und Zielarten sind je Belegart festgelegt.
*Beleg:* `InvoiceSpecificLogic.CanBeForwardedFrom()` / `CanBeForwardedInto()`.
**Bestellung** (`SupplierOrder = 7`)
Lieferantenbeleg zur Beschaffung von Waren oder Leistungen.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 140-141.
---
## C
**c-entron.NET**
Der Windows-Rich-Client der Suite (WPF/XAML, DevExpress). Kann wahlweise direkt gegen die Datenbank oder
über den Web-Service betrieben werden.
*Beleg:* `src/centron/Centron.WPF.UI`; `CentronConnectionType`.
**c-entron Nexus** (auch "c-entron Web")
Die webbasierte Anwendung auf Blazor-Basis mit den Bereichen WebCart (Shop), WebOffer (Angebotsannahme),
ServiceBoard (Ticketsicht), DocumentSigning (digitale Unterschrift) und Management.
*Beleg:* `src/nexus/CentronNexus`; `README.md`.
**CentronObjectKindNumeric**
Systemweites Enum, das jedem Fachobjekttyp einen stabilen numerischen Schlüssel zuweist. Werte ab
7 600 000 sind für Neuanlagen aus dem .NET-System reserviert; bestehende Werte dürfen nicht geändert
werden.
*Beleg:* `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 6-14.
**Checkliste** (`CentronChecklist`, `Checklist = 7600082`)
Aufgabenliste an einem Fachobjekt (u. a. am Ticket). Das Kennzeichen `CanCloseHelpdesk` steuert, ob ein
Ticket bei offenen Punkten dieser Checkliste abgeschlossen werden darf.
*Beleg:* `src/backend/Centron.DAO/Mappings/CheckListArea/CentronChecklistBaseMaps.cs` Z. 30.
**ConcurrencyControlGuid**
GUID-Feld jedes Belegs zur optimistischen Sperre. Weicht der vom Client übergebene Wert vom gespeicherten
ab, wird das Speichern mit dem Code `ChangedByOtherInstance` (10009) abgelehnt.
*Beleg:* `ReceiptBase.cs` Z. 55; `ReceiptBL.cs` Z. 4939-4940.
**Kontingent** (`Contingent`)
Vertraglich vereinbartes Leistungsvolumen (in Stunden oder Geldbetrag), gegen das erbrachte Leistungen
gebucht werden. Kennt Überbuchung (`Overbooking`), Restmitnahme (`TakeRest`), Restwert
(`ContingentResidualValue`) und Limitabrechnung (`IsContingentLimitBilling`).
*Beleg:* `ReceiptBL.WriteReceiptLogs()`; `AutomaticFacturaBL.Contracts.StoreBookedContingent()`.
---
## D
**DAOSession**
Datenbanksitzung auf NHibernate-Basis. Trägt einen Sitzungscache, in dem u. a. die Rechteliste eines
Benutzers zwischengespeichert wird.
*Beleg:* `src/backend/Centron.DAO/DAOSession.cs`; `src/backend/Centron.DAO/SessionCache.cs`.
**DBUpdate**
Tabelle, in der die bereits ausgeführten Datenbank-Migrationsskripte anhand ihrer Skriptnummer vermerkt
sind.
*Beleg:* `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs`.
**Einschränkendes Recht** (engl. *restricting right*)
Recht mit invertierter Wirkung: Sein Vorhandensein **beschränkt** den Benutzer, statt ihm etwas zu
erlauben (z. B. "Tickets anzeigen - nur eigene", "Rechnungen anzeigen - nur eigene Filiale").
*Beleg:* `CentronRights.md`; `AppRightsBL.GetAssignableAdminRightI3Ds()`.
**Distributor / Distri**
Großhändler, mit dem elektronisch Belege ausgetauscht werden (ALSO, Alltron, Herweck, Komsa u. a.).
*Beleg:* `src/backend/Centron.BL/EDI/`; `EdiDataType`.
**DSGVO-Modul**
Funktionsbereich zur Unterstützung datenschutzrechtlicher Pflichten: Verwaltung von
Auftragsverarbeitungsverträgen (`OrderProcessingContract`), Auswertung löschbarer Altdatenbestände und
Löschung personenbezogener Kontaktdaten.
*Beleg:* `src/backend/Centron.BL/Administration/Documents/Dsgvo/`;
`src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs`.
---
## E
**EDI** (Electronic Data Interchange)
Elektronischer Belegaustausch mit Lieferanten in strukturierten Formaten. Unterstützte Formate:
OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron, ZUGFeRD. Ausgetauschte Dokumentarten: Bestellung,
Bestellbestätigung, Lieferschein, Rechnung.
*Beleg:* `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs`,
`EDIConnectionObjectKind.cs`.
**Employee** (Personalstamm, Tabelle `Personal`)
Mitarbeiterdatensatz. Trägt u. a. die Filialzuordnung (`BranchI3D`), Einstellungs- und Austrittstermin,
die für die Anmeldefähigkeit ausgewertet werden.
*Beleg:* `Authenticator.ValidateAppUser()` Z. 206-216.
**ExpirationKind**
Ablaufart eines Sitzungstickets je Anwendung: `Default` (30 Minuten), `MonitoringConnector` (5 Minuten),
`FromSettings` (konfigurierbar, mindestens 30 Minuten), `OneDay` (1440 Minuten).
*Beleg:* `ApplicationKind.cs` Z. 165-171; `TicketBL.GetExpireDate()`.
---
## F
**Filiale** (`Branch`, `BranchI3D`)
Organisatorische Untereinheit eines Mandanten. Belege, Rechtegruppen und Nummernkreise können
filialbezogen geführt werden. Ein fehlender oder auf 0 gesetzter Wert gilt als Hauptfiliale.
*Beleg:* `ReceiptBL.CanUserCreateReceiptsInBranch()` Z. 10260-10265.
---
## G
**Gutschrift** (`CreditVoucherClass = 6`, Tabellen `GutKopf`/`GutPos`, View `CreditVouchers`)
Kundenbeleg zur Rückerstattung; einziger zulässiger Folgebeleg einer Rechnung.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 43-44; `InvoiceSpecificLogic.CanBeForwardedInto()`.
---
## H
**Helpdesk / Ticket** (`HelpdeskClass = 10`)
Serviceanfrage mit Status, Kategorie, Priorität, verantwortlicher Person, Bearbeitern, Historie,
Checklisten und erfassten Zeiten.
*Beleg:* `src/backend/Centron.BL/Sales/Support/`; `CentronRights.md`, Abschnitt "Helpdesk".
**HelpdeskTimer** (`HelpdeskTimerClass = 4000056`)
Erfasste Arbeitszeit an einem Ticket, gekennzeichnet als berechenbar oder nicht berechenbar
(`Calculable`). Kann genau einer Rechnungsposition zugeordnet werden (`InvoiceAssetItemI3D`); ist sie
einem Beleg zugeordnet (`IsAssignedToAsset`), ist sie gegen Löschung geschützt.
*Beleg:* `HelpdeskTimerBL.DeleteHelpdeskTimer()`; `InvoiceSpecificLogic.SetTimerToPositionReference()`.
---
## I
**I3D** ("ID 3develop")
Namenskonvention für den Primärschlüssel jeder Tabelle (`int IDENTITY(1,1) NOT NULL`, gruppierter
Primärschlüsselindex). Fremdschlüssel tragen das Muster `{Zieltabelle}I3D`.
*Beleg:* `docs/guides/database/database-conventions.md`, Abschnitte 1.2/1.3;
`src/backend/Centron.Entities/PersistedEntity.cs`.
**ILogic / BLLogic / WSLogic**
Namenskonvention des Client-Datenzugriffs: `I{Modul}Logic` ist die Schnittstelle, `BL{Modul}Logic` die
Implementierung mit direktem Datenbankzugriff, `WS{Modul}Logic` die Implementierung über den
Web-Service. Die Auflösung erfolgt über den `ClassContainer`.
*Beleg:* `docs/getting-started/general-structure.md`;
`src/centron/Centron.WPF.UI/Services/Container/ClassContainer.cs`.
---
## L
**Lieferschein** (`DeliveryListClass = 3`, Tabellen `LiefKopf`/`LiefPos`, View `DeliveryLists`)
Kundenbeleg über die Auslieferung von Waren; häufigste Quelle einer Rechnung.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 27-28.
**Lizenz**
Eine GUID, die entweder eine anmeldefähige Anwendung oder ein Einzelfunktionsmerkmal repräsentiert.
Optional mit Anzahl (`count`), Gültigkeit bis Datum und Gültigkeit bis Version versehen. Die
verbindliche Quelle ist der Lizenzserver; `LicenseGuids.cs` hält eine synchronisierte Kopie.
*Beleg:* `docs/reference/security/licensing-system.md`;
`src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs`.
**LicenseUsageKind**
Zählweise der Lizenzbelegung: `PerUserAndPerMachine` (Standard) oder `PerUser` (u. a. Service-Board).
*Beleg:* `ApplicationKind.cs` Z. 173-177.
---
## M
**Mahnstufe** (`DunningLevel`)
Eskalationsstufe einer überfälligen Rechnung: `None`, `Level1`, `Level2`, `Level3`. Je Stufe werden
Datum und auslösender Benutzer festgehalten.
*Beleg:* `src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs` Z. 253-268.
**Mahnlauf** (`DunningRun`)
Nummerierter Vorgang, der die Mahnstufe der ausgewählten Rechnungen um jeweils eine Stufe erhöht und die
Mahndokumente erzeugt. Über die Laufnummer vollständig zurücknehmbar.
*Beleg:* `DunningRunBL.ExecuteDunningRun()` / `ResetDunningRun()`.
**Mahnstopp**
Zeitlich begrenzte Aussetzung des Mahnverfahrens für ein Objekt, mit Freitextbegründung.
*Beleg:* `DunningBL.UpdateDunningStopAndInfo()` Z. 392.
**Mandant** (`Mandator`, `Company = 53`)
Oberste organisatorische Einheit. Nummernkreise werden je Mandant, ergänzt um Filialvarianten, geführt.
*Beleg:* `NumberGroupBL.RefreshAllNumberGroups()` Z. 136-152.
---
## N
**Nummernkreis** (`NumberGroup`)
Konfiguration zur Vergabe fortlaufender Belegnummern, definiert über Mandant, Filiale, Nummernart
(`NumberGroupEnum`), Bereich (`RangeFrom`/`RangeTo`), Schrittweite (`Interval`) und aktuellen Stand
(`Current`).
*Beleg:* `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs`.
---
## O
**OpenTrans 2.1**
Branchenstandard für den elektronischen Belegaustausch, im System als `EdiDataType.OpenTrans21` (Wert 1)
unterstützt.
*Beleg:* `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs` Z. 17-18.
---
## R
**Rechnung** (`InvoiceClass = 4`, Tabellen `RechKopf`/`RechPos`, View `Invoices`)
Kundenbeleg zur Zahlungsanforderung. Sonderformen: **Barrechnung** (`IsCashAsset`, eigener Nummernkreis
`CashInvoice`, keine Weiterführung möglich) und **interne Rechnung** (`InternalInvoice`, bei reinen
Dienstleistungspositionen mit Nettosumme 0).
*Beleg:* `CentronObjectKindNumeric.cs` Z. 29-30; `InvoiceSpecificLogic.GetNumberGroup()` Z. 104-141.
**Result / Result&lt;T&gt;**
Einheitliches Ergebnisobjekt aller Geschäftslogikmethoden mit `Status` (`Success`, `Warning`, `Error`),
`Message` und maschinenlesbarem `MessageCode`.
*Beleg:* `src/backend/Centron.Interfaces/Results/`.
---
## S
**Sichbenu / Sichgrup / Sichtrus / Sichmemb**
Die vier historischen Tabellen des Mitarbeiter-Rechtemodells: Benutzer, Gruppen, Gruppe-Recht-Zuordnung,
Benutzer-Gruppe-Zuordnung.
*Beleg:* `AppRightsBL.CheckRightsFromUser()` Z. 97-101; `ResetDefaultRightGroups()` Z. 587-588.
**Skriptmethode** (`ScriptMethod{Nummer}`)
Versionierte, einmalig ausgeführte Codeeinheit zur Datenbankmigration, abgelegt als C#-Klasse mit
Skriptnummer und zugeordneter Anwendungsversion. 799 Dateien mit Nummern bis 11820.
*Beleg:* `src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/`.
**SpecificLogic** (`IReceiptSpecificLogic`)
Belegartspezifische Strategieimplementierung, an die die generische Belegverarbeitung (`ReceiptBL`) alle
typabhängigen Entscheidungen delegiert. 13 Implementierungen.
*Beleg:* `src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs`, `SpecificLogics.cs`.
**Stammdat / ApplicationSettings**
Die beiden Tabellen für Anwendungseinstellungen: `Stammdat` (historisch, adressiert über
`AppSettingsConst`) und `ApplicationSettings` (aktuell, adressiert über `ApplicationSettingID`).
*Beleg:* `docs/guides/development/settings-management.md`;
`src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs`.
---
## T
**Ticket (Sitzung)**
Nicht zu verwechseln mit dem Helpdesk-Ticket. Sitzungsmerkmal, das nach erfolgreicher Anmeldung und
bestandener Lizenzprüfung ausgegeben wird und alle weiteren Web-Service-Aufrufe autorisiert. Gebunden an
Benutzer, Anwendungsart, Lizenz-GUID, Gerät und Ablaufzeitpunkt.
*Beleg:* `src/backend/Centron.BL/Administration/Logins/TicketBL.cs`.
---
## V
**Vertrag** (`ContractClass = 22`, Tabellen `VertragKopf`/`VertragPos`, View `Contracts`)
Kundenbeleg für wiederkehrende Leistungen. Trägt Abrechnungsintervall (`BillingIntervalKind` ×
`BillingIntervalDuration`), Berechnungsart (`ContractCalculationKind`), Kontingentkonfiguration,
automatische Abrechnung (`AutomatedBilling`) und automatische Verlängerung
(`AutomatedProlongation`).
*Beleg:* `CentronObjectKindNumeric.cs` Z. 55-56;
`src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs`.
**Abrechnungsintervall** (`BillingIntervalKinds`)
Rhythmus der Vertragsabrechnung: `Daily` = 0 ("Tag(e)"), `Monthly` = 1 ("Monat(e)"), `Yearly` = 2
("Jahr(e)"), `Quarterly` = 3 ("Quartal(e)"), jeweils multipliziert mit `BillingIntervalDuration`.
*Beleg:* `src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs`.
---
## W
**Wareneingang** (`SupplierDeliveryList = 8`)
Lieferantenbeleg über den Eingang bestellter Waren.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 142-143.
**WE-Kalkulation** (`SupplierInvoice = 18`)
Lieferantenbeleg zur Bewertung des Wareneingangs (Eingangsrechnungsprüfung/Kalkulation). Einzige
Belegart, für die beim Speichern eine Abschlussrückfrage gestellt wird.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 144-145; `ReceiptBL.CheckCloseReceipt()` Z. 4130-4150.
**WebAccount** (`Webaccount = 131`)
Kundenkonto für den Zugang zum Self-Service-Portal. Verfügt über ein eigenes Rechtemodell
(`WebAccountsRights`) und hat keinen Zugriff auf die interne Belegverwaltung.
*Beleg:* `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs`;
`ReceiptBL.CanUserViewReceipt()` Z. 10299-10302.
**WebCart**
Shop-Bereich des Nexus-Portals für Endkunden des Betreibers. Der Artikelkatalog stammt aus den
kundenspezifischen Sonderpreisen.
*Beleg:* `README.md`, Abschnitt "Contributing / 1. WebCart"; `src/nexus/CentronNexus/WebCart`.
**WebOffer / WebReceiptState**
Portalfunktion zur Angebotsansicht durch den Kunden mit den Rückmeldungen
`AcceptFullWebReceipt` (vollständige Annahme), `AcceptWebReceiptWithChangeRequests` (Annahme mit
Änderungswünschen), `Rejected` (Ablehnung), `WebOfferSign` (mit Unterschrift) und
`WebOfferSignedWithoutSignature` (ohne Unterschrift).
*Beleg:* `ReceiptBL.cs` Z. 5924-5928, 6302, 6360; `src/nexus/CentronNexus/WebOffer`.
---
## Z
**ZUGFeRD / XRechnung**
Standards für die elektronische Rechnung. ZUGFeRD bettet ein strukturiertes XML in das Rechnungs-PDF ein;
`IsZugferdXRechnungActive` schaltet auf die XRechnung-2.1-Variante des XML um.
*Beleg:* `src/backend/Centron.BL/EDI/Zugferd/`;
`src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs` Z. 108-111.
---
## Abkürzungen der Belegklassifikation (Methodik)
| Kennzeichen | Bedeutung |
|---|---|
| `PRIMÄR` | Im Code oder als Datenbank-Constraint durchgesetzte Regel |
| `SEKUNDÄR` | UI-Beschriftung, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter |
| `KONTEXT` | Kommentar, Commit-Nachricht, Ticketreferenz, Entwicklerdokumentation |
@@ -0,0 +1,325 @@
# Hypothesen und offene Fragen
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
---
## Vorbemerkung zur Systematik
Der Prompt verlangt, nicht eindeutig aus Artefakten ableitbare Aussagen als `[HYPOTHESE]` zu kennzeichnen.
In diesem Lauf wurde stattdessen der umgekehrte Weg gewählt: **In die Spezifikationsdokumente wurden
ausschließlich Anforderungen aufgenommen, die mindestens einen `PRIMÄR`-Beleg tragen.** Alle 71
Anforderungen (15 StRS, 32 SyRS, 24 SwRS) tragen daher den Status `belegt` bzw. `belegt; Workaround`;
keine trägt den Status `HYPOTHESE`.
Aussagen, die sich **nicht** hinreichend belegen ließen, wurden nicht zu Anforderungen formuliert, sondern
in diesem Dokument als offene Fragen gesammelt. Damit bleibt die Spezifikation frei von unbelegten
Soll-Aussagen; der Klärungsbedarf ist gleichwohl vollständig dokumentiert.
Jede Hypothese nennt: die vermutete Aussage, die vorhandenen (unzureichenden) Belege, die **fehlende
Information** und die daraus abzuleitende **offene Frage an den Fachexperten**.
---
## H-01 - Vollständigkeit des Belegstatusmodells
**[HYPOTHESE]** Das Statusmodell `ReceiptState` (offen/abgeschlossen/storniert) ist für **alle** Belegarten
identisch und kennt keine weiteren, fachlich relevanten Zwischenzustände.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` definiert genau drei Werte,
und `ReceiptBase.State` ist vom Typ `ReceiptState` - das gilt für alle Belegarten.
- `SEKUNDÄR`: In `ReceiptBL` finden sich zusätzliche, statusähnliche Konzepte, die nicht in `ReceiptState`
abgebildet sind: `WebReceiptState` (Z. 5924-5928, 6302, 6360), `FreigabeStatus` als Spalte in
`RechKopf` (`RechKopfMaps.cs`), `ReceiptCartReleaseSystemBL` (Freigabesystem für Belegkörbe),
`ReceiptUserState` (`src/backend/Centron.Entities/Entities/Sales/Receipts/UserState/`) und
`ReceiptCompleteReason`.
- `KONTEXT`: `docs/reference/receipts/receipts-backend-architecture.md` nennt abweichend vier Zustände
("Draft, Released, Processed, Cancelled"), die im Code so nicht existieren.
**Fehlende Information**
Es ist unklar, ob `FreigabeStatus`, `ReceiptUserState` und `WebReceiptState` eigenständige fachliche
Statusmaschinen darstellen, die parallel zu `ReceiptState` laufen, oder ob es sich um Attribute ohne
Zustandslogik handelt. Die Dokumentation widerspricht dem Code.
**Offene Frage**
Wie viele fachlich unterscheidbare Belegzustände gibt es tatsächlich, und in welcher Beziehung stehen
`ReceiptState`, `FreigabeStatus`, `ReceiptUserState` und `WebReceiptState` zueinander?
**Betroffene Anforderung:** SyRS-002
---
## H-02 - Behandlung des Tagesintervalls in der Vertragsabrechnung
**[HYPOTHESE]** Die Gleichbehandlung von `BillingIntervalKinds.Daily` und `.Monthly` in
`AutomaticFacturaBL.Contracts.StoreBookedContingent()` ist ein Fehler und kein beabsichtigtes Verhalten.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs`
Z. 1105-1108: `case BillingIntervalKinds.Daily: case BillingIntervalKinds.Monthly:
invoiceMonthBillingInterval = billingParam.BillingIntervalDuration; break;`
- `PRIMÄR`: `ReportObjectsBL.cs` Z. 272-274 und `ReceiptToReportObjectMap.cs` Z. 354-356 behandeln
`Daily` überhaupt nicht und fallen auf die Vorbelegung `nMonth = 1` zurück.
- `PRIMÄR`: `AutomaticFacturaBL.Contracts.cs` Z. 1060 (`if (billingParam.BillingIntervalKind ==
BillingIntervalKinds.Daily)`) zeigt, dass `Daily` an anderer Stelle sehr wohl gesondert behandelt wird.
**Fehlende Information**
Es fehlt eine Aussage darüber, ob Verträge mit Tagesintervall im Produktivbetrieb tatsächlich vorkommen.
Ohne Datenbestand lässt sich nicht entscheiden, ob es sich um toten Code oder um einen wirksamen
Berechnungsfehler handelt.
**Offene Frage**
Werden Verträge mit `BillingIntervalKind = Daily` produktiv genutzt? Falls ja: Welcher
Abrechnungszeitraum ist fachlich korrekt?
**Betroffene Anforderungen:** SyRS-019, SwRS-022
---
## H-03 - Wirksamkeit der Belegabschluss-Prüfung im Helpdesk
**[HYPOTHESE]** Der Abschluss eines Helpdesk-Tickets über `HelpdeskCloseBL.CloseHelpdesk()` umgeht die
Checklistenprüfung, weil `HelpdeskCloseBL.CanCloseHelpdesk()` unbedingt `true` zurückgibt.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs` Z. 129 ruft `CanCloseHelpdesk`,
Z. 158-165 gibt diese `return true;` mit dem Kommentar `//Todo: if rma exists check if finished` zurück.
- `PRIMÄR`: `UpdateHelpdeskBL.CanHelpdeskClose()` (Z. 492-518) und
`HelpdeskWebServiceBL.CanHelpdeskClose()` (Z. 283-309) enthalten die tatsächliche Prüfung.
**Fehlende Information**
Es ließ sich nicht abschließend ermitteln, ob alle Aufrufwege zum Ticketabschluss (Rich Client, Nexus,
Web-Service, automatische Prozesse) vorher `UpdateHelpdeskBL.CanHelpdeskClose` bzw.
`HelpdeskWebServiceBL.CanHelpdeskClose` aufrufen, oder ob mindestens ein Weg direkt auf
`HelpdeskCloseBL.CloseHelpdesk` geht. Eine vollständige Aufrufanalyse über alle Clients war im Rahmen
dieses Laufs nicht möglich.
**Offene Frage**
Existiert ein produktiv erreichbarer Weg, ein Ticket mit offenen Pflicht-Checklistenpunkten
abzuschließen?
**Betroffene Anforderung:** SyRS-017
---
## H-04 - Funktionsfähigkeit der DSGVO-Datenbereinigung
**[HYPOTHESE]** Die Funktion "Datenbank bereinigen" führt derzeit keine Löschung durch.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs` Z. 63-68:
`DataSecurityExecuteCleanUp` prüft Recht und Feature und gibt danach unmittelbar
`Result.AsSuccess()` zurück; der Parameter `selectedStats` wird nicht ausgewertet.
- `SEKUNDÄR`: Das Recht 20800024 "Datenbank bereinigen" existiert (`AppRightsBL.
GetAssignableAdminRightI3Ds()` Z. 757) und ein UI-Modul `Modules.Administration.DSGVO` ist registriert.
- `SEKUNDÄR`: `DsgvoDeleteRightDeleteContacts` (Z. 787) ist demgegenüber ausimplementiert.
**Fehlende Information**
Unklar bleibt, ob die Löschung an anderer Stelle (z. B. clientseitig oder über einen Hintergrunddienst)
ausgeführt wird oder ob die Methode ein unvollständiger Stand ist. Eine Ausführung des Systems war nicht
Teil des Auftrags.
**Offene Frage**
Ist die Datenbankbereinigung ein produktiv genutztes Feature? Falls ja: Wo findet die eigentliche
Löschung statt?
**Betroffene Anforderungen:** StRS-012, SyRS-025
---
## H-05 - Invalidierung des Rechte-Zwischenspeichers
**[HYPOTHESE]** Eine Rechteänderung wirkt für einen bereits angemeldeten Benutzer erst nach einer neuen
Datenbanksitzung, weil der Rechte-Cache nicht invalidiert wird.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 646:
`Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", () =>
GetAllAppRightsFromUser(appUserI3D))` - kein Invalidierungsaufruf in den ändernden Methoden
(`AddRightToRightGroup`, `RemoveRightFromRightGroup`, `AddUserToRightGroup`, …).
- `PRIMÄR`: `src/backend/Centron.DAO/SessionCache.cs` bindet den Cache an die `DAOSession`.
**Fehlende Information**
Die Lebensdauer einer `DAOSession` im Web-Service-Betrieb ließ sich nicht abschließend bestimmen. Ist sie
je Aufruf neu (`using (BLSession session = new BLSession())` im `AuthenticateInterceptor` deutet darauf
hin), ist die Auswirkung vernachlässigbar; ist sie langlebig, entsteht ein Sicherheitsrisiko bei
Rechteentzug.
**Offene Frage**
Wie lange lebt eine `DAOSession` im Web-Service? Wird ein Rechteentzug für einen aktiven Benutzer sofort
wirksam?
**Betroffene Anforderungen:** SyRS-006, SwRS-017
---
## H-06 - Vorrangregel bei der ZUGFeRD-Aktivierung
**[HYPOTHESE]** Die belegbezogene ZUGFeRD-Einstellung (`GetLocalZUGFeRDSetting(receipt)`) kann die globale
Einstellung nur aktivieren, nicht deaktivieren.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 3273: die Bedingung lautet
`(new InvoiceZugferdBL(Session).IsZugferdEnabled() || this.GetLocalZUGFeRDSetting(receipt) == true)` -
eine ODER-Verknüpfung, die keine Deaktivierung durch die belegbezogene Einstellung erlaubt.
**Fehlende Information**
Es fehlt eine fachliche Aussage darüber, ob ein einzelner Beleg bewusst **ohne** ZUGFeRD-XML erzeugt
werden können soll, obwohl die Funktion global aktiviert ist (z. B. bei Auslandskunden).
**Offene Frage**
Soll die belegbezogene Einstellung die globale auch abschalten können?
**Betroffene Anforderung:** SyRS-024
---
## H-07 - Verbindlichkeit der Dokumentation als Anforderungsquelle
**[HYPOTHESE]** Die Inhalte unter `docs/` beschreiben den Ist-Zustand zuverlässig genug, um als
ergänzende Anforderungsquelle zu dienen.
**Vorhandene Belege**
- `SEKUNDÄR`: 50 Markdown-Dokumente mit teilweise sehr hoher Detailtiefe (u. a. 28 005 Bytes
ZUGFeRD-Feldzuordnung, 18 771 Bytes Belegarchitektur) und konkreten Datei- und Zeilenverweisen, die
sich in Stichproben als zutreffend erwiesen (z. B. Belegart-/Tabellenzuordnung, `AnlageArt`-Werte).
- `KONTEXT`: **Gegenbeleg** - `docs/reference/receipts/receipts-backend-architecture.md`, Abschnitt
"Receipt State Management", nennt vier Zustände (Draft, Released, Processed, Cancelled), die im Code
nicht existieren (siehe H-01).
- `KONTEXT`: **Gegenbeleg** - `docs/getting-started/general-structure.md` weist selbst darauf hin, dass
die beschriebene Struktur vielfach nicht eingehalten ist.
- `KONTEXT`: `docs/getting-started/documentation-rules.md` und
`docs/getting-started/ai-codebase-navigation.md` deuten darauf hin, dass Teile der Dokumentation
werkzeuggestützt erzeugt wurden.
**Fehlende Information**
Es ist unbekannt, welche Dokumente redaktionell geprüft wurden und welche generiert sind. Da mindestens
ein Dokument nachweislich vom Code abweicht, ist die Verlässlichkeit uneinheitlich.
**Offene Frage**
Welche Dokumente unter `docs/` sind fachlich abgenommen und dürfen als Anforderungsquelle gelten?
**Konsequenz für diese Spezifikation:** Dokumentationsinhalte wurden durchgängig nur als `KONTEXT`
klassifiziert und nie als alleiniger Beleg einer Anforderung verwendet.
---
## H-08 - Umfang des Delphi-Altsystems im Zielsystem
**[HYPOTHESE]** Ein Teil des Fachverhaltens wird weiterhin von einem Delphi-Altsystem (c-entron Delphi,
Versionsschema 9.3.x) erbracht, das dieselbe Datenbank und dieselben Lizenzen nutzt.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs`,
`TryFixCentronDelphiVersionNumber()` (Z. 304-330) mit dem Kommentar "The c-entron Delphi uses the same
license-guid as the c-entron.NET, but has a version-number like 9.3.X.Y" und dem daraus folgenden
Verzicht auf die Versionsprüfung für Delphi-Clients.
- `PRIMÄR`: `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 14: "Neue Konstanten für .Net
werden autark von c-entron Delphi angelegt Sie beginnen ab dem Wert 7600000".
- `SEKUNDÄR`: Die durchgängig deutschen Alttabellennamen (`RechKopf`, `AngPos`, `Sichbenu`, `Sichgrup`,
`Sichtrus`, `Sichmemb`, `Stammdat`, `Kunden`, `Kreditor`, `Taetigkeiten`) legen einen gemeinsamen
Ursprung nahe.
**Fehlende Information**
Der Delphi-Quellcode liegt nicht im Arbeitsverzeichnis. Es lässt sich daher nicht bestimmen, welche
Fachfunktionen ausschließlich dort implementiert sind und in dieser Spezifikation folglich fehlen.
**Offene Frage**
Welche Fachfunktionen werden heute ausschließlich vom Delphi-System erbracht, und sind sie Teil des
Migrationsumfangs?
**Konsequenz:** Diese Spezifikation beschreibt ausschließlich das .NET-System. Ein möglicher blinder Fleck
ist im `Analysebericht.md` als Lücke L-01 vermerkt.
---
## H-09 - Verbindlichkeit der Datenbankkonventionen für den Altbestand
**[HYPOTHESE]** Die in `docs/guides/database/database-conventions.md` geforderten Nachverfolgungs- und
Soft-Delete-Spalten sind nur in neueren Tabellen tatsächlich vorhanden.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.DAO/Mappings/TemporaryEntities/RechKopfMaps.cs` bildet die Alttabelle
`RechKopf` ab und verwendet abweichende Spaltennamen (`ErstelltDurch`, `GeaendertVonI3D`, `ErstellerI3D`,
`KundenID`, `AnschriftID`) statt der konventionsgemäßen `CreatedByI3D`/`ChangedByI3D`.
- `PRIMÄR`: `docs/guides/database/database-conventions.md`, Abschnitt 4: "Historical tables and columns may
use German names … Do not rename existing German table/column names".
**Fehlende Information**
Ohne Datenbankzugriff (es liegen keine `.sql`-Dateien im Repository, das Schema entsteht ausschließlich
zur Laufzeit über die 799 Skriptmethoden) lässt sich der tatsächliche Anteil konventionskonformer Tabellen
nicht bestimmen.
**Offene Frage**
Wie hoch ist der Anteil der Tabellen ohne vollständige Audit- und Soft-Delete-Spalten, und ist eine
Vereinheitlichung im Zielsystem vorgesehen?
**Betroffene Anforderungen:** SwRS-006, SwRS-007
---
## H-10 - Kennwortmigration bei der Neuimplementierung
**[HYPOTHESE]** Bestehende Kennwörter können bei einer Migration nicht in ein modernes Hashverfahren
überführt werden, ohne dass die Benutzer sich mindestens einmal anmelden oder ihr Kennwort zurücksetzen.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.Common/TextCoding/SHA1Decoder.cs` erzeugt einen nicht umkehrbaren Hash;
Klartextkennwörter liegen nicht vor.
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs` Z. 48:
`// TODO the password should be salted!!!`
**Fehlende Information**
Es ist nicht bekannt, ob im Zielsystem ein Übergangsbetrieb vorgesehen ist, in dem beide Verfahren
parallel geprüft werden, oder ob ein organisatorischer Kennwort-Reset akzeptabel ist.
**Offene Frage**
Wie soll die Kennwortmigration erfolgen - schrittweises Neuhashen bei der nächsten Anmeldung oder
vollständiger Reset?
**Betroffene Anforderung:** SwRS-009
---
## H-11 - Fachliche Bedeutung der 750 Rechtekonstanten
**[HYPOTHESE]** Ein relevanter Teil der 750 definierten Rechte ist nicht mehr in Verwendung.
**Vorhandene Belege**
- `PRIMÄR`: `UserRightsConst.cs` enthält 750 aktive und mehrere auskommentierte Konstanten, teils mit
Hinweisen wie `//public const int //RECHTDESMENUITEMSWIRDIMPROGRAMMAUCHGEBRAUCHTRIGHT_WARTUNG=10480;`
und `//public const int //WARTUNGC-WIMRIGHT_VERTRAGSARTEN=10492;`.
- `SEKUNDÄR`: `CentronRights.md` dokumentiert für das Recht `RIGHT_KALENDERANZEIGENALLE` ausdrücklich:
"Currently, this right is not used."
- `SEKUNDÄR`: `AppRightsBL.ResetDefaultRightGroups()` stellt eine Standardstruktur her, die nicht
notwendigerweise alle 750 Rechte abdeckt.
**Fehlende Information**
Eine belastbare Verwendungsanalyse aller 750 Rechtekonstanten über die gesamte Codebasis (16 063
`.cs`-Dateien plus 1233 XAML- und 491 Razor-Dateien) wurde in diesem Lauf nicht durchgeführt.
**Offene Frage**
Welche Rechte sind produktiv relevant und in das Zielsystem zu übernehmen?
**Betroffene Anforderung:** StRS-003
---
## 12. Zusammenfassung
| Nr. | Thema | Risikoschwerpunkt | Priorität für die Validierung |
|---|---|---|---|
| H-01 | Vollständigkeit des Belegstatusmodells | Fakturierung | hoch |
| H-02 | Tagesintervall in der Vertragsabrechnung | Fakturierung | hoch |
| H-03 | Umgehbare Ticketabschluss-Prüfung | Prozessintegrität | hoch |
| H-04 | Wirkungslose DSGVO-Bereinigung | Recht/Datenschutz | hoch |
| H-05 | Invalidierung des Rechte-Caches | Sicherheit | hoch |
| H-06 | Vorrangregel ZUGFeRD | E-Rechnung | mittel |
| H-07 | Verlässlichkeit der Dokumentation | Methodik | mittel |
| H-08 | Umfang des Delphi-Altsystems | Migrationsumfang | hoch |
| H-09 | Konventionskonformität des Altschemas | Datenmigration | mittel |
| H-10 | Kennwortmigration | Sicherheit/Migration | hoch |
| H-11 | Nutzungsgrad der 750 Rechte | Migrationsumfang | mittel |
@@ -0,0 +1,661 @@
# StRS - Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE c-entron ERP)
**Erstellt durch:** Reverse Requirements Engineering (statische Artefaktanalyse)
**Norm:** ISO/IEC/IEEE 29148:2018, Abschnitt 9.3 (Stakeholder Requirements Specification)
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha` (`version.json`)
**Datum:** 2026-08-25
---
## 1. Zweck und Geltungsbereich
Dieses Dokument beschreibt die aus der Codebasis rekonstruierten Anforderungen aus Sicht der Stakeholder (Fachbereiche, Endanwender, Betreiber, Kunden des Betreibers). Es bildet die oberste Ebene der dreistufigen Spezifikation (StRS → SyRS → SwRS).
Alle Aussagen sind aus lesbaren Artefakten des Arbeitsverzeichnisses abgeleitet. Jede Anforderung trennt die belegte technische Beobachtung (`Fakt`) von der fachlichen Interpretation (`Aussage`).
## 2. Systemüberblick
c-entron ist eine ERP-Suite für den deutschen Markt mit Schwerpunkt IT-Systemhaus/IT-Dienstleistung. Sie besteht aus:
| Teilsystem | Technologie | Pfad |
|---|---|---|
| c-entron.NET (Rich Client) | WPF/XAML, DevExpress | `src/centron/Centron.WPF.UI` |
| Web-Service (Backend-API) | ASP.NET Core, WCF-Bridge, NHibernate | `src/webservice/`, `src/backend/` |
| c-entron Nexus (c-entron Web) | Blazor, DevExpress Blazor | `src/nexus/CentronNexus` |
| Outlook Add-In | Office Add-In | `src/nexus/CentronNexus.OutlookAddIn` |
| Fremdsystem-Konnektoren | .NET Bibliotheken | `src/apis/`, `src/backend/Centron.Gateway` |
## 3. Stakeholder (aus Artefakten abgeleitet)
| Stakeholder | Beleg für Existenz der Rolle |
|---|---|
| Mitarbeiter/Sachbearbeiter (`AppUser`, `Employee`) | `src/backend/Centron.Entities/Entities/Administration/…` (`AppUser`), Tabelle `Sichbenu` |
| Rechteadministrator | `UserRightsConst.Administration.UserRightsManagement`, `AppRightsBL.SaveRightGroup` |
| Kunde des Betreibers (Web-Account) | `WebAccount`, `WebAccountAuthenticator`, `src/nexus/CentronNexus/WebCart` |
| Buchhaltung/Forderungsmanagement | `DunningBL`, `DunningRunBL`, `UserRightsConst.Controlling.Finances` |
| Servicetechniker/Helpdesk-Bearbeiter | `HelpdeskTimerBL`, `CentronRights.md` Abschnitt Helpdesk |
| Betreiber/IT-Administrator | `docker/`, `deployment/WixSharpInstaller`, `nlog.config` |
| Lieferant (via EDI) | `src/backend/Centron.BL/EDI/`, `SupplierEdiConfigurations` |
| Lizenzgeber (NEXOWARE Systems GmbH) | `Directory.Build.props` (`<Company>`), `LicenseManager`, Lizenzserver-Anbindung |
---
## 4. Stakeholder-Anforderungen
---
```
ID: StRS-001
Titel: Durchgängige Belegkette im Vertriebsprozess
Ebene: StRS
Typ: funktional
Akteur: Sachbearbeiter Vertrieb
Vorbedingung: Angemeldeter Benutzer mit Belegrechten; Kunde im Stammsatz vorhanden
Fakt: Das Enum `CentronObjectKindNumeric` definiert die Kundenbelegarten Angebot (1), Auftrag (2),
Lieferschein (3), Rechnung (4), Abholschein (5), Gutschrift (6), Vertrag (22) und stellt die
Prüfmethode `IsCustomerReceipt()` bereit, die genau diese sieben Arten als Kundenbeleg wertet.
`InvoiceSpecificLogic.CanBeForwardedFrom()` gibt an, dass eine Rechnung aus Lieferschein,
Auftrag, Angebot und Vertrag entstehen kann, `CanBeForwardedInto()` erlaubt die Weiterführung
in eine Gutschrift.
Aussage: Das System soll den kaufmännischen Vertriebsprozess über die Belegarten Angebot, Auftrag,
Lieferschein, Abholschein, Rechnung, Gutschrift und Vertrag abbilden und die Weiterführung
eines Belegs in einen Folgebeleg unterstützen, wobei die zulässigen Übergänge je Belegart
definiert sind.
Ergebnis: Aus einem Vorgängerbeleg entsteht ein Folgebeleg mit übernommenen Positionen; die Herkunft
bleibt über die Beleghistorie nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Zeilen 23-30, 41-44, 55-56 sowie
Methode `CentronObjectKindNumericExtensions.IsCustomerReceipt()` (Z. 273-287) - Begründung: Die
Belegarten sind als typisierte Konstanten im Code festgelegt und werden zur Laufzeit zur
Klassifikation herangezogen; damit ist der Belegartenumfang durchgesetzt, nicht nur dokumentiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs,
`CanBeForwardedFrom()` / `CanBeForwardedInto()` (Z. 279-280) - Begründung: Die Methoden liefern
die erlaubten Quell-/Zielbelegarten und werden vom generischen `ReceiptBL` zur Steuerung der
Weiterführung ausgewertet; die Belegkette ist damit im Code erzwungen.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs,
`GetAssetName()` (Z. 303-317) mit den UI-Bezeichnungen "Angebot", "Auftrag", "Lieferschein",
"Abholschein", "Rechnung", "Gutschrift", "Vertrag" - Begründung: Belegt die fachlichen
Bezeichnungen, unter denen die Belegarten dem Anwender präsentiert werden.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md, Tabelle "Receipt Types Hierarchy" -
Begründung: Bestätigt die Zuordnung Belegart → Entität → Tabelle → View aus Entwicklersicht.
Prüfidee: Für jede der sieben Kundenbelegarten kann ein Beleg angelegt werden; eine Rechnung lässt sich
aus Lieferschein/Auftrag/Angebot/Vertrag erzeugen und in eine Gutschrift weiterführen; die
Weiterführung einer Rechnung in einen Auftrag wird abgelehnt.
Tracelinks: SyRS-001, SyRS-002, SyRS-003
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-002
Titel: Mandanten- und Filialorganisation
Ebene: StRS
Typ: funktional
Akteur: Betreiber mit mehreren Standorten
Vorbedingung: Mindestens ein Mandant (`Mandator`) angelegt
Fakt: `NumberGroupBL.RefreshAllNumberGroups()` ermittelt den Default-Mandanten und legt für jede
Filiale (`BranchBL.GetBaseBranchList`) eigene Nummernkreise an. `ReceiptBase` besitzt die
Felder `BranchI3D` und `BranchOrigin`. `AppRightsBL.GetAllRightGroups()` filtert Rechtegruppen
auf die Filiale des Benutzers, wenn dieser das Recht `MANAGE_RIGHTS_ONLY_OWN_BRANCH` besitzt.
`ApplicationKind`/`LicenseGuids` führen eine eigene Lizenz für die Filialfunktionalität.
Aussage: Das System soll den Betrieb mehrerer Mandanten und Filialen innerhalb einer Installation
unterstützen und Datenobjekte (Belege, Rechtegruppen, Nummernkreise) einer Filiale zuordnen
können.
Ergebnis: Belege, Nummernkreise und Rechtegruppen sind filialbezogen führbar; filialbezogene
Einschränkungen sind auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs,
`RefreshAllNumberGroups()` (Z. 136-152) - Begründung: Der Code legt je Filiale einen eigenen
Satz Nummernkreise an; die Filialstruktur ist damit strukturbildend, nicht nur ein Attribut.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Z. 19-20
(`BranchI3D`, `BranchOrigin`) - Begründung: Jeder Beleg trägt eine Filialzuordnung als
persistiertes Feld der Basisklasse aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `GetAllRightGroups()` (Z. 39-48)
und `SaveRightGroup()` (Z. 391-393) - Begründung: Filialgrenzen werden bei der
Rechteverwaltung serverseitig durchgesetzt.
- [KONTEXT] docs/reference/security/licensing-system.md, Abschnitt "Only Licenses" nennt die
"branch functionality" als separat lizenzierbares Einzelfeature - Begründung: Zeigt, dass die
Filialfunktion ein eigenständiges, kommerziell abgegrenztes Fachmerkmal ist.
Prüfidee: Nach Anlage einer zweiten Filiale existieren für diese eigene Nummernkreiseinträge; ein Beleg
dieser Filiale trägt deren `BranchI3D`.
Tracelinks: SyRS-004, SyRS-005
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-003
Titel: Rollenbasierte Zugriffssteuerung über Rechtegruppen
Ebene: StRS
Typ: Sicherheit
Akteur: Rechteadministrator
Vorbedingung: Benutzer (`AppUser`) und Rechtegruppen (`AppGroup`) existieren
Fakt: Die Datei `UserRightsConst.cs` definiert 750 als `public const int` deklarierte Rechte-IDs in
einer fachlich gegliederten Klassenhierarchie (z. B. `Sales.Customer.Helpdesk`,
`Administration.UserRightsManagement`, `Controlling.Finances`). Rechte werden nicht direkt an
Benutzer, sondern über die Tabellen `Sichtrus` (Gruppe→Recht) und `Sichmemb` (Benutzer→Gruppe)
vergeben; `AppRightsBL.CheckRightsFromUser()` verknüpft beide per SQL-Join.
Aussage: Das System soll Zugriffsrechte fein granular (mindestens auf Funktions- und Modulebene)
definieren und ausschließlich über Gruppenzugehörigkeit an Benutzer vergeben.
Ergebnis: Ein Benutzer erhält genau die Rechte der Gruppen, denen er angehört; die Rechtevergabe ist
zentral über Gruppen administrierbar.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs
(2819 Zeilen, 750 Rechtekonstanten) - Begründung: Die Rechte-IDs sind der im gesamten Code
verwendete Schlüssel für Berechtigungsprüfungen; ihre Existenz und Granularität ist damit
durchgesetzt.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `CheckRightsFromUser()`
(Z. 95-111) mit dem SQL `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON
sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D` - Begründung: Das Statement zeigt das
durchgesetzte Datenmodell Benutzer→Gruppe→Recht.
- [SEKUNDÄR] CentronRights.md (Repository-Wurzel) - Begründung: Beschreibt die fachliche Bedeutung
einzelner Rechte, insbesondere das Konzept "restricting right" (einschränkende Rechte).
- [KONTEXT] docs/guides/development/check-userrights.md - Begründung: Dokumentiert die verbindliche
Prüfmethodik für Entwickler.
Prüfidee: Ein Benutzer ohne Gruppenzugehörigkeit erhält aus `CheckRightsFromUser` eine leere Rechteliste;
nach Aufnahme in eine Gruppe mit Recht X enthält die Liste X.
Tracelinks: SyRS-006, SyRS-007, SyRS-008
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-004
Titel: Lizenzabhängiger Funktionsumfang
Ebene: StRS
Typ: funktional / Sicherheit
Akteur: Lizenzgeber, Betreiber
Vorbedingung: Lizenzdatei vom Lizenzserver bezogen oder aus Cache verfügbar
Fakt: `LicenseManager` prüft je Lizenz-GUID Vorhandensein (`HasLicense`), Anzahl (`GetLicenseCount`)
und Gültigkeit bis Version (`CheckLicenseVersion`). `ApplicationKind` definiert 44 anmeldefähige
Anwendungen, jeweils mit Lizenz-GUID, Ablaufart (`ExpirationKind`) und Nutzungsart
(`LicenseUsageKind`). `AccessTokenBL.ValidateToken()` bricht mit "Sie haben nicht die
notwendige Lizenz!" ab, wenn `LicenseGuids.AccessTokenModule` fehlt.
Aussage: Das System soll den nutzbaren Funktionsumfang je Installation über Lizenzen steuern, wobei
Lizenzen sowohl ganze Anwendungen als auch einzelne Funktionsmerkmale abdecken und optional
mengen- sowie versions- bzw. datumsbegrenzt sein können.
Ergebnis: Nicht lizenzierte Anwendungen können sich nicht anmelden; nicht lizenzierte Einzelfunktionen
sind nicht nutzbar oder werden nicht angezeigt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, `CheckLicense()`
(Z. 258-302) - Begründung: Setzt Lizenzprüfung inkl. Mengenbegrenzung als harte Fehlerbedingung
beim Anmeldevorgang durch.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs, Z. 11-53 -
Begründung: Enthält die abschließende Liste anmeldefähiger Anwendungen mit ihren
Lizenz-GUIDs; `ApplicationKind.GetKindByLicenseGuid()` wird beim Login zwingend ausgewertet.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs, `ValidateToken()`
(Z. 381-383) - Begründung: Beispiel für eine Einzelfunktion, deren Nutzung an eine Lizenz
gebunden ist und die ohne Lizenz einen Fehler zurückgibt.
- [KONTEXT] docs/reference/security/licensing-system.md - Begründung: Erläutert das Lizenzmodell
(GUID, count, valid until date, valid until version) aus Herstellersicht.
Prüfidee: Eine Anmeldung mit einer Anwendung, deren Lizenz-GUID nicht in der Lizenzdatei enthalten ist,
wird mit Lizenzfehler abgewiesen; ein Aufruf der Access-Token-Validierung ohne Modullizenz
liefert die Fehlermeldung "Sie haben nicht die notwendige Lizenz!".
Tracelinks: SyRS-014, SyRS-015
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-005
Titel: Serviceprozess über Helpdesk-Tickets
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Helpdesk-Bearbeiter
Vorbedingung: Benutzer besitzt das Recht `SHOW_HELPDESK`
Fakt: Es existiert ein eigenständiges Ticketsystem mit ca. 50 BL-Klassen unter
`src/backend/Centron.BL/Sales/Support/` (u. a. `HelpdeskBL`, `HelpdeskStatusBL`,
`HelpdeskCategoryBL`, `HelpdeskCloseBL`, `HelpdeskForwardBL`, `HelpdeskSchedulerBL`,
`HelpdeskTimerBL`). `CentronObjectKindNumeric.HelpdeskClass = 10` weist das Ticket als
eigenständige Objektart aus. `CentronRights.md` listet 18 Hauptrechte und mehrere
einschränkende Rechte allein für den Helpdesk.
Aussage: Das System soll Serviceanfragen als Tickets mit Status, Kategorie, Priorität, verantwortlicher
Person, Bearbeitern, Historie und Checklisten führen und deren Lebenszyklus bis zum Abschluss
steuern.
Ergebnis: Ein Ticket durchläuft definierte Status bis zum Abschlussstatus; alle Änderungen sind über die
Tickethistorie nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/ (Verzeichnis, ca. 50 BL-Klassen; u. a.
`HelpdeskCloseBL.cs`, `HelpdeskHistoryBL.cs`, `HelpdeskStatusBL.cs`) - Begründung: Umfang und
Struktur der implementierten Logik belegen den eigenständigen Fachprozess.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs, `CloseHelpdesk()` (Z. 120-155):
Setzt `helpdeskRequest.Data.HelpdeskState = closedState` und löscht zugehörige ToDos -
Begründung: Der Abschlussvorgang ist als durchgesetzter Zustandsübergang implementiert.
- [SEKUNDÄR] CentronRights.md, Abschnitt "Helpdesk" (18 nummerierte Rechte) - Begründung: Zeigt die
fachliche Feingliederung des Prozesses aus Anwendersicht.
- [KONTEXT] docs/features/automatic-helpdesk-creation-templates.md (29 852 Bytes) - Begründung: Beschreibt
die automatisierte Ticketerzeugung als ausgebautes Teilfeature.
Prüfidee: Ein Ticket kann angelegt, einem Bearbeiter zugewiesen, kategorisiert und abgeschlossen werden;
nach Abschluss trägt es den in den Einstellungen hinterlegten Abschlussstatus.
Tracelinks: SyRS-017
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-006
Titel: Leistungserfassung und Überführung in die Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Abrechnung
Vorbedingung: Ticket existiert; Benutzer besitzt das Recht `EDIT_TIME`
Fakt: `HelpdeskTimer` besitzt die Felder `Calculable` (berechenbar), `Start`, `Stop`, `Article`,
`InvoiceAssetItemI3D` und `IsAssignedToAsset`. `InvoiceSpecificLogic.SetTimerToPositionReference()`
wirft eine Exception mit dem Text "Die Zeit (I3D {…}) wurde bereits durch eine andere
Rechnungsposition (I3D {…}) abgerechnet.", wenn eine Zeit bereits einer anderen
Rechnungsposition zugeordnet ist. `HelpdeskTimerBL.DeleteHelpdeskTimer()` verweigert das Löschen
mit "Die Helpdesk Zeit wurde einem Beleg zugewiesen. Löschen ist nicht möglich.".
Aussage: Das System soll erfasste Arbeitszeiten mit Kennzeichnung ihrer Berechenbarkeit führen, sie
genau einer Abrechnungsposition zuordnen können und bereits abgerechnete Zeiten gegen Löschung
und Mehrfachabrechnung schützen.
Ergebnis: Eine erfasste Zeit ist höchstens einer Rechnungsposition zugeordnet; abgerechnete Zeiten sind
unveränderlich gegenüber Löschung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs,
`SetTimerToPositionReference()` (Z. 615-623) - Begründung: Verhindert per Exception die
Doppelabrechnung derselben Zeit; das ist eine durchgesetzte Abrechnungsregel.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs, `DeleteHelpdeskTimer()` (Z. 553-565) -
Begründung: Rechteprüfung (`DELETE_HELPDESK_TIMER`) und Sperre bei Belegzuordnung sind
serverseitig implementiert.
- [SEKUNDÄR] CentronRights.md, Abschnitte 8 und 9 ("Helpdeskzeiten verschieben"/"löschen": "But only if the
ticket is not part of a receipt.") - Begründung: Bestätigt die Regel aus Anwendersicht.
- [KONTEXT] Commit `0afd60a422` "Fix timer type (Calculable) (#98)" - Begründung: Belegt, dass die
Berechenbarkeitskennzeichnung aktiv gepflegtes Fachverhalten ist.
Prüfidee: Eine Zeit, die einer Rechnungsposition zugeordnet ist, kann nicht gelöscht werden; der Versuch,
sie einer zweiten Rechnungsposition zuzuordnen, führt zu einem Fehler.
Tracelinks: SyRS-018
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-007
Titel: Vertrags- und Abonnementgeschäft mit wiederkehrender Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Vertragsverwaltung, Abrechnung
Vorbedingung: Vertrag (Belegart `ContractClass`) mit Abrechnungsintervall angelegt
Fakt: Der Vertrag ist eine eigene Belegart (`CentronObjectKindNumeric.ContractClass = 22`,
Beschreibung "Vertrag"). `BillingIntervalKinds` definiert die Intervalle Tag(e)=0, Monat(e)=1,
Jahr(e)=2, Quartal(e)=3. `AutomaticFacturaBL.Contracts` (Teil eines ca. 6100-Zeilen-Komplexes)
berechnet Abrechnungszeiträume, Kontingentverbräuche und erzeugt Rechnungen aus Verträgen.
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall (Tag, Monat, Quartal, Jahr
jeweils mit Faktor) führen und daraus wiederkehrend Rechnungen erzeugen können, einschließlich
Verbrauchs- und Kontingentabrechnung.
Ergebnis: Zum jeweiligen Abrechnungstermin entstehen Rechnungen mit dem vertraglich vereinbarten Umfang;
Kontingentverbräuche werden fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs,
Z. 8-22 - Begründung: Legt die zulässigen Abrechnungsintervalle typisiert fest.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs,
`StoreBookedContingent()` (Z. 1098-1120) und `isFirstIntervalDay()` (Z. 1355-1373) -
Begründung: Zeigt die durchgesetzte Umrechnung von Intervallart in Abrechnungsmonate und die
Prüfung auf Intervallbeginn.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Z. 55-58: `[Description("Vertrag")]
ContractClass = 22` und `[Description("Vertragsart")] ContractKindClass = 86` - Begründung:
Belegt Vertrag und Vertragsart als eigenständige Fachobjekte.
- [KONTEXT] docs/reference/receipts/contracts-backend.md, Abschnitte "Billing Configuration" und
"Automated Billing Process" - Begründung: Beschreibt die Vertragsabrechnung aus
Entwicklersicht, einschließlich Kontingent- und Zählerlogik.
Prüfidee: Ein Vertrag mit `BillingIntervalKind = Quarterly` und `BillingIntervalDuration = 1` erzeugt
beim Lauf der automatischen Fakturierung eine Rechnung über einen Zeitraum von drei Monaten.
Tracelinks: SyRS-019
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-008
Titel: Mehrstufiges Mahnwesen
Ebene: StRS
Typ: funktional
Akteur: Forderungsmanagement / Buchhaltung
Vorbedingung: Offene, fällige Rechnung; Benutzer hat Zugriff auf das Mahnmodul
Fakt: `DunningRunBL.ExecuteDunningRun()` erhöht die Mahnstufe einer Rechnung entlang der Kette
`DunningLevel.None → Level1 → Level2 → Level3` und protokolliert je Stufe Datum
(`DunningLevel1Date` …) und auslösenden Benutzer (`DunningLevel1Employee` …).
`DunningRunBL.ResetDunningRun()` setzt die jeweils erreichte Stufe wieder zurück.
`DunningBL` kennt zusätzlich einen Mahnstopp (`UpdateDunningStopAndInfo` mit
`dunningStopBegin`/`dunningStopEnd`).
Aussage: Das System soll ein mehrstufiges Mahnverfahren mit maximal drei Mahnstufen unterstützen, jede
Stufenerhöhung mit Datum und auslösendem Benutzer protokollieren, Mahnläufe zurücknehmen können
und einen zeitlich begrenzten Mahnstopp je Objekt erlauben.
Ergebnis: Eine überfällige Rechnung wird je Mahnlauf um genau eine Stufe erhöht (max. Stufe 3);
ein zurückgenommener Mahnlauf stellt den Vorzustand her.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs, Z. 253-268
(`switch (invoice.DunningLevel)` mit den Übergängen None→Level1→Level2→Level3) - Begründung:
Die Statusmaschine des Mahnwesens ist im Code implementiert und begrenzt die Stufenzahl.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs,
`ResetDunningRun()` (Z. 495-535) - Begründung: Belegt die Rücknahmefähigkeit als eigenständige
Fachfunktion mit Rücksetzung von Datum und Bearbeiter.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs,
`UpdateDunningStopAndInfo()` (Z. 392) - Begründung: Mahnstopp mit Zeitraum ist als
persistierte Eigenschaft implementiert.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs,
`CalculateDunningStatistics()` (Z. 207-230) mit Auswertung genau der Stufen 0-3 - Begründung:
Bestätigt die Stufenanzahl über die Auswertungslogik.
Prüfidee: Eine Rechnung in Stufe 3 wird durch einen weiteren Mahnlauf nicht weiter erhöht; nach
`ResetDunningRun` steht die Rechnung wieder auf der vorherigen Stufe mit geleerten
Stufenfeldern.
Tracelinks: SyRS-020
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-009
Titel: Beschaffungsprozess mit elektronischer Lieferantenanbindung
Ebene: StRS
Typ: funktional / Schnittstelle
Akteur: Einkauf, Lieferant
Vorbedingung: Lieferanten-EDI-Konfiguration hinterlegt
Fakt: `CentronObjectKindNumeric` definiert die Lieferantenbelegarten Anfrage (15), Bestellung (7),
Wareneingang (8), WE-Kalkulation (18) und Lieferantengutschrift (148); `IsSupplierReceipt()`
fasst sie zusammen. Unter `src/backend/Centron.BL/EDI/` existieren Implementierungen für ALSO,
AlsoCH, Alltron, Komsa, Concerto, EGIS, OpenTrans 2.1 und ZUGFeRD. `EdiDataType` und
`EDIConnectionObjectKind` definieren Formate und Dokumentarten typisiert.
Aussage: Das System soll den Beschaffungsprozess über eigene Lieferantenbelegarten abbilden und
Bestellungen, Auftragsbestätigungen, Lieferscheine und Rechnungen elektronisch mit
Distributoren austauschen können.
Ergebnis: Eingehende EDI-Dokumente aktualisieren die zugehörigen Bestellungen bzw. erzeugen Folgebelege;
ausgehende Bestellungen werden im vereinbarten Format übertragen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Z. 139-147 und
`IsSupplierReceipt()` (Z. 289-301) - Begründung: Die Lieferantenbelegarten sind typisiert
festgelegt und werden zur Laufzeit klassifiziert.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs, Z. 12-27 und
src/webservice/Centron.WebServices.Core/Entities/EDI/EDIConnectionObjectKind.cs, Z. 12-22 -
Begründung: Format- und Dokumentartenumfang sind als Enums durchgesetzt und Teil des
Web-Service-Vertrags (`[EnumMember]`).
- [SEKUNDÄR] src/backend/Centron.BL/EDI/ (Unterverzeichnisse ALSO, Alltron, AlsoCH, Concerto, EGIS, Komsa,
Opentrans21, Zugferd, SupplierEDI, Import) - Begründung: Die Verzeichnisstruktur belegt den
Umfang der real unterstützten Lieferantenformate.
- [KONTEXT] docs/reference/edi/edi-architecture.md, Tabelle "Document Types Supported" - Begründung:
Ordnet je Lieferant zu, welche Dokumentarten unterstützt werden.
Prüfidee: Für einen konfigurierten Lieferanten wird ein OpenTrans-2.1-Auftragsbestätigungsdokument
eingelesen und der zugehörigen Bestellung zugeordnet; das Ergebnis erscheint im EDI-Protokoll.
Tracelinks: SyRS-021, SyRS-022
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-010
Titel: Self-Service-Portal für Endkunden
Ebene: StRS
Typ: funktional
Akteur: Kunde des Betreibers (Web-Account)
Vorbedingung: Web-Account im Adressstamm angelegt und aktiv
Fakt: `src/nexus/CentronNexus` enthält die Bereiche `WebCart` (Shop), `WebOffer` (Angebotsansicht mit
Annahme), `ServiceBoard` (Ticketsicht), `DocumentSigning` (digitale Unterschrift) und
`Management`. `WebAccountAuthenticator`/`WebAccountBL.LoginWithWebAccount()` implementieren
eine eigene Anmeldung für Kundenkonten. `WebReceiptState` kennt die Werte
`AcceptFullWebReceipt`, `AcceptWebReceiptWithChangeRequests`, `Rejected`, `WebOfferSign`,
`WebOfferSignedWithoutSignature`.
Aussage: Das System soll Endkunden des Betreibers einen webbasierten Zugang bereitstellen, über den sie
Angebote einsehen, annehmen, ablehnen oder mit Änderungswünschen versehen, Dokumente digital
unterschreiben, Tickets einsehen und aus einem Sonderpreiskatalog bestellen können.
Ergebnis: Die Kundenentscheidung (Annahme/Ablehnung/Unterschrift) wird am Beleg gespeichert und ist im
ERP sichtbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 5924-5928 (Auswertung von
`WebReceiptState.AcceptFullWebReceipt` / `AcceptWebReceiptWithChangeRequests` / `Rejected`)
und Z. 6302, 6360 (`WebOfferSign`, `WebOfferSignedWithoutSignature`) - Begründung: Die
Kundenrückmeldung aus dem Portal wird im Backend als Belegzustand verarbeitet.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs,
`LoginWithWebAccount()` (Z. 54-95) - Begründung: Eigener Anmeldeweg für Kundenkonten inkl.
Aktivitäts- und Sperrprüfung von Kontakt, Adresse und Kunde.
- [SEKUNDÄR] src/nexus/CentronNexus/ (Verzeichnisse `WebCart`, `WebOffer`, `ServiceBoard`,
`DocumentSigning`) sowie `docker/deploy/appsettings.json` Abschnitt `WebAccount` -
Begründung: Belegt die im Portal umgesetzten Fachbereiche und ihre Konfigurierbarkeit.
- [KONTEXT] README.md, Abschnitt "Contributing / 1. WebCart": "The webcart is a feature primarily intended
for the customers of our customers … The available articles come from the customers
'Sonderpreise'" - Begründung: Nennt Zielgruppe und Preisquelle des Shops explizit.
Prüfidee: Ein Web-Account kann sich anmelden, ein freigegebenes Angebot einsehen und annehmen; der
Belegzustand im ERP wechselt entsprechend.
Tracelinks: SyRS-023
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-011
Titel: Elektronische Rechnungsstellung nach ZUGFeRD/XRechnung
Ebene: StRS
Typ: funktional / Schnittstelle
Akteur: Rechnungsstellung, Rechnungsempfänger (auch öffentliche Auftraggeber)
Vorbedingung: Einstellung `IsZugferdInvoiceActive` aktiviert
Fakt: `ApplicationSettingID` enthält u. a. `IsZugferdInvoiceActive` (10028),
`IsZugferdXRechnungActive`, `AppendZugferdInvoiceXmlToMails`, `ActiveZugferdInterface`,
`ZugferdExportPreferMandatorNameOverBranchName`, `ZugferdExportDontExportArticleCode`,
`ZugferdExportDontExportEanCode`, `ZugferdSellerContactPersonKind`. Die Beschreibung zu
`IsZugferdXRechnungActive` lautet: "If this settings is active, ZUGFeRD PDF file will contain
new version of XML file (XRechnung 2.1)." Unter `src/backend/Centron.BL/EDI/Zugferd/` liegen
`ZUGFeRD_BL.cs` und `ZugferdParseBL.cs`.
Aussage: Das System soll Rechnungen zusätzlich zum PDF in maschinenlesbarer Form nach ZUGFeRD bzw.
XRechnung erzeugen, den Umfang der übertragenen Felder konfigurierbar halten und eingehende
ZUGFeRD-Rechnungen einlesen können.
Ergebnis: Eine erzeugte Rechnung enthält bei aktivierter Einstellung ein eingebettetes, standardkonformes
XML; der Versand per E-Mail kann das XML zusätzlich anhängen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs, Z. 223
(`IsZugferdInvoiceActive = 10028`) und
src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs,
Z. 108-111, 506-514, 770 - Begründung: Die Konfigurationsschalter sind typisiert definiert und
steuern das Laufzeitverhalten der Rechnungserzeugung.
- [PRIMÄR] src/backend/Centron.BL/EDI/Zugferd/ZUGFeRD_BL.cs und ZugferdParseBL.cs - Begründung: Erzeugung
und Parsen sind als eigene Fachlogik implementiert (Ein- und Ausgangsrichtung).
- [SEKUNDÄR] docs/reference/zugferd-feldzuordnung-anwender.md (28 005 Bytes) und
docs/reference/zugferd-field-mapping.md (24 769 Bytes) - Begründung: Detaillierte
Feldzuordnungstabellen belegen den fachlichen Abdeckungsgrad der Schnittstelle.
- [KONTEXT] Commit `7d62212022` "Fix: Correct discount calculation to retain sign for ZUGFeRD total check
integrity (#112)" - Begründung: Belegt, dass die Summenkonsistenz des ZUGFeRD-Dokuments aktiv
validiert wird.
Prüfidee: Bei aktivierter Einstellung enthält das erzeugte Rechnungs-PDF ein eingebettetes XML, das die
KOSIT-Validierung für XRechnung besteht.
Tracelinks: SyRS-024
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-012
Titel: Unterstützung datenschutzrechtlicher Pflichten (DSGVO)
Ebene: StRS
Typ: Sicherheit / rechtlich
Akteur: Datenschutzverantwortlicher, Administrator
Vorbedingung: Benutzer besitzt das Recht `DsgvoModule.ACCESS_CLEANUP_DATABASE`
Fakt: Es existieren ein eigenes DSGVO-Modul (`src/backend/Centron.BL/Administration/Documents/Dsgvo/`,
`DsgvoBL`) mit Verwaltung von Auftragsverarbeitungsverträgen (`OrderProcessingContract`,
Objektart 7600085) sowie eine Datenbereinigung (`DataSecurityBL`) mit alters- und
objektartabhängigen Statistiken und einer Löschfunktion für Kontakte
(`DsgvoDeleteRightDeleteContacts`). Die UI führt ein eigenes Modul
`Modules.Administration.DSGVO`.
Aussage: Das System soll die Erfüllung datenschutzrechtlicher Pflichten unterstützen, insbesondere die
Verwaltung von Auftragsverarbeitungsverträgen, die Auswertung löschbarer Altdatenbestände und
die gezielte Löschung personenbezogener Kontaktdaten, jeweils gebunden an ein eigenes Recht.
Ergebnis: Ein Datenschutzverantwortlicher kann Altdatenbestände auswerten und Kontaktdaten löschen;
Auftragsverarbeitungsverträge sind je Kunde dokumentiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs,
`DataSecurityExecuteCleanUp()` (Z. 63-68): Prüfung
`currentUser.HasUserRight(UserRightsConst.DsgvoModule.ACCESS_CLEANUP_DATABASE)` und
`ModuleFeatures.IsDsgvoDatabaseCleanupAvailable` - Begründung: Rechte- und Feature-Bindung der
Bereinigung ist serverseitig implementiert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Documents/Dsgvo/DsgvoBL.cs (Verwaltung von
`OrderProcessingContractTemplate` inkl. Audit-Feldern `CreatedBy`/`ChangedBy`) - Begründung:
Auftragsverarbeitungsverträge sind als persistierte, revisionsfähige Objekte implementiert.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, Meldungstexte wie
"Es gibt {n} CRM-Einträge die älter als {Datum} sind." - Begründung: Zeigt die
Löschfristensystematik aus Anwendersicht.
- [KONTEXT] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Namespace-Import
`Modules.Administration.DSGVO` - Begründung: Belegt das DSGVO-Modul als eigenständigen
Einstiegspunkt in der Oberfläche.
Prüfidee: Ein Benutzer ohne `ACCESS_CLEANUP_DATABASE` erhält bei Aufruf der Bereinigung die Meldung
"Insufficient rights!".
Tracelinks: SyRS-025
Konsolidierung: nein
Status: belegt; Workaround
Anmerkung: Siehe SyRS-025 - die Methode `DataSecurityExecuteCleanUp` führt nach der Rechteprüfung keine
Löschoperation aus, sondern gibt unmittelbar Erfolg zurück.
```
---
```
ID: StRS-013
Titel: Nachvollziehbarkeit von Geschäftsvorfällen
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Sicherheit / Verantwortlichkeit)
Akteur: Revision, Fachbereichsleitung
Vorbedingung: Änderung an einem Beleg, Ticket oder an Rechten
Fakt: `ReceiptBase` führt die Felder `CreatedByI3D`, `CreatedAt`, `CreatedThroughApplicationVersion`,
`ChangedByI3D`, `ChangedAt`, `ChangedThroughApplicationVersion`, `ChangedThroughApplication`
und `Version`. `ReceiptBL.WriteReceiptLogs()` schreibt für jede geänderte Kontingent- und
Bankverbindungseigenschaft einen eigenen Protokolleintrag über `ReceiptLogBL`. `AppRightsBL`
protokolliert jede Rechte-/Gruppenänderung als `AppRightLog` mit Benutzer, Zeitpunkt und
Anwendungsversion. `AccessTokenLogBL` protokolliert Tokennutzung inkl. API-Methode und
IP-Adresse.
Aussage: Das System soll für geschäftsrelevante Objekte (Belege, Rechte, Zugriffstoken) festhalten, wer
wann mit welcher Anwendungsversion welche Änderung vorgenommen hat, und diese Historie
auswertbar bereitstellen.
Ergebnis: Zu jedem Beleg, jeder Rechteänderung und jeder Tokennutzung ist der Verursacher und der
Zeitpunkt ermittelbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Z. 46-52 (Audit-Felder
inkl. Anwendungsversion) - Begründung: Die Nachvollziehbarkeitsfelder sind Teil der
persistierten Basisklasse aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `WriteBaseLog()` (Z. 762-781)
mit `CreatedByI3D`, `CreatedDate`, `CreatedVersion` - Begründung: Rechteänderungen werden
zwingend protokolliert; die Methode wird aus allen ändernden Operationen aufgerufen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `WriteReceiptLogs()` (ab Z. 10313) -
Begründung: Feldgenaue Änderungsprotokollierung für abrechnungsrelevante Belegattribute.
- [SEKUNDÄR] docs/guides/database/database-conventions.md, Abschnitt 2 "Standard Tracking Columns"
(`CreatedByI3D`, `CreatedDate`, `ChangedByI3D`, `ChangedDate`, Soft-Delete-Spalten) -
Begründung: Verbindliche Konvention für alle neuen Tabellen.
Prüfidee: Nach Änderung eines Belegs sind `ChangedByI3D`, `ChangedAt` und
`ChangedThroughApplicationVersion` aktualisiert; nach Entzug eines Rechts existiert ein
`AppRightLog`-Eintrag mit Text "Recht … der Gruppe … entzogen".
Tracelinks: SyRS-008, SyRS-026, SyRS-030
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-014
Titel: Deutschsprachiger Zielmarkt mit optionaler englischer Oberfläche
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Gebrauchstauglichkeit)
Akteur: Endanwender
Vorbedingung: keine
Fakt: Zu jeder Ressourcendatei `LocalizedStrings.resx` existiert genau eine Übersetzungsdatei
`LocalizedStrings.en.resx` (Backend, WPF-Client, Controls); im Nexus entsprechend
`SharedResource.resx` / `SharedResource.en-US.resx`. Fehlermeldungen im Backend werden in
deutscher Sprache erzeugt (z. B. "Sie haben nicht genügend Rechte um eine Gruppe anlegen zu
können.", "Die maximale Anzahl an Lizenzen wurde erreicht.").
Aussage: Das System soll Deutsch als Standardsprache der Oberfläche und aller Anwendermeldungen führen
und zusätzlich Englisch als vollständige Alternativsprache bereitstellen.
Ergebnis: Anwender erhalten alle Meldungen in Deutsch; bei englischer Spracheinstellung stehen
übersetzte Ressourcen bereit.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Resources/LocalizedStrings.resx und LocalizedStrings.en.resx;
src/centron/Centron.WPF.UI/Resources/LocalizedStrings.resx und .en.resx;
src/shared/Centron.Controls/Resources/LocalizedStrings.resx und .en.resx -
Begründung: Das durchgängige Paar Basis-/Englisch-Ressource ist der technische Mechanismus,
der die Zweisprachigkeit trägt.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 357, 389, 396 (deutsche
Fehlermeldungen im Backend) - Begründung: Belegt Deutsch als Sprache der fachlichen Meldungen
auch außerhalb der Oberfläche.
- [SEKUNDÄR] ResXManager.config.xml (Repository-Wurzel) - Begründung: Belegt ein etabliertes Werkzeug zur
Ressourcenpflege und damit einen gelebten Übersetzungsprozess.
- [KONTEXT] docs/getting-started/general-structure.md, Abschnitt "German-First Language Policy":
"Because c-entron.NET is developed specifically for the German market, all user-facing content
must adhere to the following guidelines" - Begründung: Erklärt die Marktausrichtung als
bewusste Vorgabe.
Prüfidee: Für jeden Schlüssel in `LocalizedStrings.resx` existiert ein Eintrag in
`LocalizedStrings.en.resx`; die Oberfläche zeigt bei Umschaltung auf Englisch keine deutschen
Restbestände in geprüften Masken.
Tracelinks: SyRS-028
Konsolidierung: Kandidat: Die Lokalisierung ist auf vier voneinander unabhängige Ressourcensätze verteilt
(Centron.BL, Centron.WPF.UI, Centron.Controls, CentronNexus) - im Zielsystem ist ein
gemeinsamer Ressourcenbestand zu prüfen.
Status: belegt
```
---
```
ID: StRS-015
Titel: Betrieb wahlweise als On-Premises-Installation oder containerisierter Dienst
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Übertragbarkeit)
Akteur: Betreiber / IT-Administrator
Vorbedingung: Microsoft SQL Server verfügbar
Fakt: Es existieren nebeneinander (a) ein Windows-Installer-Projekt
(`deployment/WixSharpInstaller`), (b) ein Windows-Dienst-Host
(`src/webservice/Centron.Host.WindowsService`), (c) ein Konsolen-Host
(`src/webservice/Centron.Host.Console`) und (d) Container-Definitionen unter `docker/`
(u. a. `docker/Dockerfile` für den Nexus-Host auf Alpine Linux, `docker/c-entron-webservice`,
`docker/compose`). `docs/guides/services/web-service-on-linux.md` beschreibt den Linux-Betrieb.
Der Nexus-Container setzt `TZ=Europe/Berlin` und
`DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false`.
Aussage: Das System soll sowohl als klassische Windows-Installation (Client, Windows-Dienst) als auch
als containerisierter Dienst unter Linux betreibbar sein, wobei Zeitzone und
Globalisierungsverhalten für den deutschen Markt vorkonfiguriert sind.
Ergebnis: Der Web-Service und der Nexus-Webclient sind auf Windows und in Linux-Containern lauffähig;
der Rich Client bleibt Windows-gebunden.
Belege:
- [PRIMÄR] docker/Dockerfile, Z. 1-30 (`dotnet publish CentronNexus.Host.csproj --self-contained`,
Runtime-Image `dotnet/runtime:10.0.5-alpine3.23`, `ENV TZ=Europe/Berlin`,
`ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false`) - Begründung: Der Containerbetrieb ist
vollständig als reproduzierbarer Build definiert, inkl. der Kulturvoraussetzungen.
- [PRIMÄR] src/webservice/Centron.Host.WindowsService/ (Projekt inkl. eigener nlog.config) und
deployment/WixSharpInstaller/WixSharpInstaller.csproj - Begründung: Belegt den parallelen
klassischen Installationspfad.
- [SEKUNDÄR] docker/deploy/appsettings.json, Abschnitte `Host.Url`, `Host.LinuxCertificatePath`,
`Host.LinuxCertificatePassword`, `CentronWebService.Url` - Begründung: Konfigurationsschalter
speziell für den Linux-/Containerbetrieb inkl. TLS-Zertifikat.
- [KONTEXT] docs/guides/services/web-service-on-linux.md - Begründung: Beschreibt den Linux-Betrieb als
unterstützten Weg.
Prüfidee: Der Nexus-Host startet aus dem Container-Image und beantwortet Anfragen unter der in
`Host.Url` konfigurierten Adresse; der Web-Service läuft parallel als Windows-Dienst.
Tracelinks: SyRS-031, SyRS-032
Konsolidierung: nein
Status: belegt
```
---
## 5. Abgrenzungen auf StRS-Ebene
Folgende Bereiche sind in der Codebasis erkennbar vorhanden, wurden in dieser Iteration aber **nicht** zu
eigenen Stakeholder-Anforderungen ausgearbeitet (siehe `Analysebericht.md`, Abschnitt Lücken):
Lagerwirtschaft/Inventur, Produktion/PLM, Kassenbuch, Online-Banking/Zahlungsverkehr, CRM-Kampagnen,
Projektmanagement, Asset-/Inventarmanagement (Riversuite/DocuBoard), TAPI-Telefonie, Reportengine,
Mailscanner, Statistik/Dashboards, KI-Chat-Modul.
@@ -0,0 +1,149 @@
# Traceability-Matrix
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
Die Matrix stellt die Forward- und Backward-Traceability zwischen den drei Spezifikationsebenen her.
Die in `StRS.md`, `SyRS.md` und `SwRS.md` je Anforderung im Feld `Tracelinks` angegebenen Verweise wurden
zu einer symmetrischen Relation zusammengeführt (siehe `Analysebericht.md`, Abschnitt 6.3).
---
## 1. Haupttabelle (eine Zeile je SyRS-Anforderung)
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (Leitbeleg) |
|---|---|---|---|
| StRS-001 | SyRS-001 Belegarten und Klassifikation | SwRS-003, SwRS-004, SwRS-006, SwRS-008 | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 20-264, 266-301 |
| StRS-001, StRS-013 | SyRS-002 Belegstatusmodell | SwRS-015, SwRS-016 | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` Z. 6-14; `ReceiptBL.cs` Z. 796-797, 4936-4950 |
| StRS-001 | SyRS-003 Belegweiterführung | SwRS-013, SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs` Z. 279-297, 673 |
| StRS-001, StRS-002 | SyRS-004 Belegnummernvergabe | SwRS-014 | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs` Z. 62-134 |
| StRS-002, StRS-003 | SyRS-005 Filialbeschränkung | SwRS-016 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 10251-10295 |
| StRS-003 | SyRS-006 Serverseitige Rechtedurchsetzung | SwRS-002, SwRS-016, SwRS-017, SwRS-018, SwRS-023 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 644-709 |
| StRS-003 | SyRS-007 Verwaltung von Rechtegruppen | SwRS-016 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 348-404, 261-278, 563-612 |
| StRS-003, StRS-013 | SyRS-008 Protokollierung von Rechteänderungen | SwRS-007 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 762-857 |
| StRS-003, StRS-004 | SyRS-009 Ticketbasierte API-Authentifizierung | SwRS-010, SwRS-023 | `src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs` Z. 22-136 |
| StRS-003, StRS-004 | SyRS-010 Authentifizierungsverfahren | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs` Z. 44-188 |
| StRS-003 | SyRS-011 Zwei-Faktor-Authentifizierung | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs` Z. 32-120 |
| StRS-003 | SyRS-012 Kontosperrung und -deaktivierung | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` Z. 157-218 |
| StRS-003, StRS-004, StRS-013 | SyRS-013 API-Access-Tokens | SwRS-011, SwRS-023 | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs` Z. 377-487 |
| StRS-004 | SyRS-014 Lizenzprüfung beim Login | SwRS-010, SwRS-018 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` Z. 68-155; `LicenseManager.cs` Z. 219-236 |
| StRS-004 | SyRS-015 Lizenzanzahlbegrenzung | SwRS-010 | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs` Z. 258-302 |
| StRS-004 | SyRS-016 Ticketgültigkeitsdauer | SwRS-010, SwRS-019 | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs` Z. 26-28, 113-164 |
| StRS-005 | SyRS-017 Ticketabschluss mit Checklistenprüfung | SwRS-015 | `src/backend/Centron.BL/Sales/Support/UpdateHelpdeskBL.cs` Z. 492-518 |
| StRS-006, StRS-013 | SyRS-018 Schutz abgerechneter Zeiten | SwRS-016 | `src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs` Z. 553-605 |
| StRS-007 | SyRS-019 Vertragsabrechnungsintervalle | SwRS-012, SwRS-022 | `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs` Z. 1098-1130, 1355-1373 |
| StRS-008, StRS-013 | SyRS-020 Mahnläufe und Rücknahme | SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs` Z. 253-268, 495-535 |
| StRS-009 | SyRS-021 EDI-Formate und Dokumentarten | SwRS-008, SwRS-015 | `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs` Z. 12-27; `EDIConnectionObjectKind.cs` Z. 12-22 |
| StRS-009, StRS-013 | SyRS-022 EDI-Protokollierung | SwRS-002 | `src/backend/Centron.Interfaces/EDI/EDILogState.cs` Z. 9-19 |
| StRS-003, StRS-010 | SyRS-023 Portalzugang für Kundenkonten | SwRS-009, SwRS-017 | `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs` Z. 54-95 |
| StRS-011 | SyRS-024 Elektronische Rechnung ZUGFeRD/XRechnung | SwRS-012, SwRS-013, SwRS-019 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 3272-3292; `ApplicationSettingDefinitions.cs` Z. 108-111 |
| StRS-012 | SyRS-025 DSGVO-Auswertung und -Löschung | SwRS-016 | `src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs` Z. 34-68, 377, 787 |
| StRS-001, StRS-013 | SyRS-026 Belegversionierung | SwRS-003, SwRS-005, SwRS-007 | `src/backend/Centron.DAO/Mappings/Sales/Receipts/Invoices/ReceiptInvoiceVersionMaps.cs` Z. 5-20 |
| StRS-013 | SyRS-027 Optimistische Sperre | SwRS-024 | `src/backend/Centron.Entities/…/ReceiptBase.cs` Z. 55; `ReceiptBL.cs` Z. 4939-4940 |
| StRS-014 | SyRS-028 Mehrsprachigkeit | SwRS-021 | `src/backend/Centron.BL/Resources/LocalizedStrings.resx` / `LocalizedStrings.en.resx` |
| StRS-004, StRS-015 | SyRS-029 Automatisches Datenbank-Update | SwRS-020 | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs` Z. 39-130 |
| StRS-013, StRS-015 | SyRS-030 Betriebsprotokollierung | SwRS-002 | `src/webservice/Centron.Host.WindowsService/nlog.config` |
| StRS-015 | SyRS-031 Auslieferungs- und Betriebsformen | SwRS-020 | `version.json`; `Directory.Build.props` Z. 6-40; `docker/Dockerfile` |
| StRS-015 | SyRS-032 Zwei Zugriffswege des Clients | SwRS-001, SwRS-018 | `src/backend/Centron.Interfaces/Administration/Connections/CentronConnectionType.cs` Z. 6-12 |
---
## 2. Abdeckungsmatrix StRS → SyRS (Forward)
| StRS-ID | Titel | abgedeckt durch SyRS |
|---|---|---|
| StRS-001 | Durchgängige Belegkette im Vertriebsprozess | SyRS-001, SyRS-002, SyRS-003, SyRS-004, SyRS-026 |
| StRS-002 | Mandanten- und Filialorganisation | SyRS-004, SyRS-005 |
| StRS-003 | Rollenbasierte Zugriffssteuerung | SyRS-005, SyRS-006, SyRS-007, SyRS-008, SyRS-009, SyRS-010, SyRS-011, SyRS-012, SyRS-013, SyRS-023 |
| StRS-004 | Lizenzabhängiger Funktionsumfang | SyRS-009, SyRS-010, SyRS-013, SyRS-014, SyRS-015, SyRS-016, SyRS-029 |
| StRS-005 | Serviceprozess über Helpdesk-Tickets | SyRS-017 |
| StRS-006 | Leistungserfassung und Abrechnung | SyRS-018 |
| StRS-007 | Vertrags- und Abonnementgeschäft | SyRS-019 |
| StRS-008 | Mehrstufiges Mahnwesen | SyRS-020 |
| StRS-009 | Beschaffung und Lieferantenintegration | SyRS-021, SyRS-022 |
| StRS-010 | Self-Service-Portal für Endkunden | SyRS-023 |
| StRS-011 | Elektronische Rechnungsstellung | SyRS-024 |
| StRS-012 | Datenschutzkonformität (DSGVO) | SyRS-025 |
| StRS-013 | Nachvollziehbarkeit von Geschäftsvorfällen | SyRS-002, SyRS-008, SyRS-013, SyRS-018, SyRS-020, SyRS-022, SyRS-026, SyRS-027, SyRS-030 |
| StRS-014 | Deutschsprachiger Zielmarkt | SyRS-028 |
| StRS-015 | Betriebsmodelle | SyRS-029, SyRS-030, SyRS-031, SyRS-032 |
**Ergebnis:** Alle 15 StRS-Anforderungen sind durch mindestens eine SyRS-Anforderung abgedeckt.
---
## 3. Abdeckungsmatrix SwRS → SyRS (Backward)
| SwRS-ID | Titel | konkretisiert SyRS |
|---|---|---|
| SwRS-001 | Schichtenmodell mit doppelter Datenzugriffsimplementierung | SyRS-032 |
| SwRS-002 | Einheitliches Ergebnis- und Fehlermodell | SyRS-006, SyRS-022, SyRS-030 |
| SwRS-003 | Doppelter Persistenzpfad für Belege | SyRS-001, SyRS-026 |
| SwRS-004 | Zweischichtiges Datenbankschema | SyRS-001, SyRS-026 |
| SwRS-005 | Versionstabellen als strukturgleiche Kopien | SyRS-026 |
| SwRS-006 | Primär-/Fremdschlüsselkonvention I3D | SyRS-001 |
| SwRS-007 | Standardisierte Nachverfolgungsspalten | SyRS-008, SyRS-026 |
| SwRS-008 | Rückwärtskompatible Enum-Erweiterung | SyRS-001, SyRS-021 |
| SwRS-009 | Speicherung und Prüfung von Kennwörtern | SyRS-010, SyRS-011, SyRS-012, SyRS-023 |
| SwRS-010 | Erzeugung und Struktur von Sitzungstickets | SyRS-009, SyRS-014, SyRS-015, SyRS-016 |
| SwRS-011 | Erzeugung und Speicherung von Access-Tokens | SyRS-013 |
| SwRS-012 | Preisberechnung mit definierter Rundung | SyRS-019, SyRS-024 |
| SwRS-013 | Umsatzsteuerberechnung | SyRS-003, SyRS-024 |
| SwRS-014 | Nebenläufigkeitssichere Nummernvergabe | SyRS-004 |
| SwRS-015 | Belegartspezifische Logik (Strategiemuster) | SyRS-002, SyRS-003, SyRS-017, SyRS-020, SyRS-021 |
| SwRS-016 | Rechteprüfungen in der Geschäftslogik | SyRS-002, SyRS-005, SyRS-006, SyRS-007, SyRS-018, SyRS-025 |
| SwRS-017 | Zwischenspeicherung von Benutzerrechten | SyRS-006, SyRS-023 |
| SwRS-018 | Rechte-/lizenzabhängige Modulregistrierung | SyRS-006, SyRS-014, SyRS-032 |
| SwRS-019 | Zweigeteilte Einstellungsverwaltung | SyRS-016, SyRS-024 |
| SwRS-020 | Skriptbasierte Datenbankmigration | SyRS-029, SyRS-031 |
| SwRS-021 | Lokalisierung über .resx-Ressourcen | SyRS-028 |
| SwRS-022 | Umrechnung von Abrechnungsintervallen | SyRS-019 |
| SwRS-023 | Interceptor-Kette des Web-Service | SyRS-006, SyRS-009, SyRS-013 |
| SwRS-024 | Explizite Belegsperre | SyRS-027 |
**Ergebnis:** Alle 24 SwRS-Anforderungen referenzieren mindestens eine existierende SyRS-Anforderung.
---
## 4. SyRS-Anforderungen ohne SwRS-Konkretisierung
Alle 32 SyRS-Anforderungen sind durch mindestens eine SwRS-Anforderung konkretisiert. Die geringste
Konkretisierungstiefe weisen auf:
| SyRS-ID | Anzahl SwRS | Bemerkung |
|---|---|---|
| SyRS-022 (EDI-Protokollierung) | 1 (SwRS-002) | Die EDI-Verarbeitungslogik selbst wurde nicht auf SwRS-Ebene ausgearbeitet - siehe `Analysebericht.md`, Lücke L-03. |
| SyRS-025 (DSGVO) | 1 (SwRS-016) | Löschmechanik nicht ausgearbeitet; offene Frage H-04. |
| SyRS-027 (Optimistische Sperre) | 1 (SwRS-024) | ausreichend |
| SyRS-028 (Mehrsprachigkeit) | 1 (SwRS-021) | ausreichend |
| SyRS-031 (Auslieferungsformen) | 1 (SwRS-020) | Build-/Signaturkette nicht auf SwRS-Ebene ausgearbeitet. |
---
## 5. Konsolidierungskandidaten (Redundanzregister)
Zusammenstellung aller Anforderungen, deren Feld `Konsolidierung` einen Kandidaten benennt. Diese Fälle sind
bei der Zielarchitektur vorrangig zu entscheiden.
| Nr. | Betroffene Anforderungen | Redundante fachliche Funktion | Fundstellen |
|---|---|---|---|
| K-01 | SyRS-006, SwRS-016 | Rechteprüfung eines Benutzers (4 Mechanismen) | `AppUser.HasUserRight`; `AppRightsBL.HasUserRight` (gecacht/SQL); `AppRightsBL.CheckRightsFromUser` (SQL, Menge); `AppRightsBL.GetRightsFromCurrentUser` (Objektgraph) |
| K-02 | SyRS-017 | Prüfung "Ticket abschließbar?" (3 Implementierungen, davon eine wirkungslos) | `UpdateHelpdeskBL.CanHelpdeskClose` Z. 492; `HelpdeskWebServiceBL.CanHelpdeskClose` Z. 283; `HelpdeskCloseBL.CanCloseHelpdesk` Z. 158 (`return true;`) |
| K-03 | SyRS-019, SwRS-022 | Umrechnung Abrechnungsintervall → Monate (3 Implementierungen, `Daily` abweichend) | `AutomaticFacturaBL.Contracts.cs` Z. 1104; `ReportObjectsBL.cs` Z. 272; `ReceiptToReportObjectMap.cs` Z. 354 |
| K-04 | SyRS-002 | Übergang eines Belegs nach "abgeschlossen" (4 Auslöser) | `ReceiptBL.CheckCloseReceipt` Z. 4130; `CheckCloseRMADeliverylistReceipt` Z. 4152; `UpdateReceiptStateFromPaymentCondition` Z. 8336; Zahlungssetzung Z. 4944 |
| K-05 | SyRS-005 | Filialprüfung (Anlage vs. Bearbeitung, zwei Null-Behandlungen) | `ReceiptBL.CanUserCreateReceiptsInBranch` Z. 10251; `CanUserEditReceipt` Z. 10272 |
| K-06 | SwRS-003, SwRS-004 | Belegpersistenz (modernes View-Mapping vs. Legacy-Save-Repository) | `ReceiptInvoiceMaps.cs`; `RechKopfMaps.cs`; `SaveReceiptInvoiceRepository` |
| K-07 | SwRS-009 | Hashverfahren (3 Varianten) | `SHA1Decoder` (ohne Salt); `CryptoUtils.CreatePasswordHash` (SHA-1 mit Salt); `AccessTokenBL.HashToken` (SHA-256) |
| K-08 | SwRS-001, SyRS-032 | Datenzugriff je Modul (BL- und WS-Implementierung) | alle `I*Logic` / `BL*Logic` / `WS*Logic` |
| K-09 | SwRS-002, SwRS-023 | Fehler-/Antwortmodell (2 Modelle) | `Result`/`Result<T>` vs. `Response`/`StatusCode` |
| K-10 | SwRS-019 | Anwendungseinstellungen (2 Tabellen, 2 Schlüsselenums) | `Stammdat`/`AppSettingsConst` vs. `ApplicationSettings`/`ApplicationSettingID` |
| K-11 | SwRS-020 | Datenbankmigration (2 Mechanismen) | C#-Skriptklassen vs. `SQLScriptCollection*.xaml` |
| K-12 | SyRS-028, StRS-014, SwRS-021 | Lokalisierungsressourcen (4 getrennte Sätze) | Centron.BL, Centron.WPF.UI, Centron.Controls, CentronNexus |
| K-13 | SyRS-030 | Protokollierungskonfiguration (4 getrennte Konfigurationen) | 3 × `nlog.config` + `appsettings.json` |
| K-14 | SyRS-023 | Rechtemodell (Mitarbeiter vs. Web-Account) und Kontaktmodell (`AddressContactI3D` vs. `AccountAddressContactI3D`) | `Sichtrus`/`Sichmemb` vs. `WebAccountsRights`; `WebAccountBL.LoginWithWebAccount` Z. 68/82 |
| K-15 | SyRS-024 | ZUGFeRD-Aktivierung (global vs. belegbezogen) | `InvoiceZugferdBL.IsZugferdEnabled()` vs. `ReceiptBL.GetLocalZUGFeRDSetting(receipt)` |
| K-16 | SwRS-006 | Fremdschlüsselbenennung (`…I3D` vs. historisch `…ID`) | `RechKopfMaps.cs` (`KundenID`, `AnschriftID`, `PersonID`) |
| K-17 | SwRS-012 | Preisberechnung in `double` und `decimal` | `CalculationUtils.cs` (parallele Überladungen) |
| K-18 | SwRS-015 | Zu breite Belegschnittstelle (~100 Methoden, teils mit Ausnahmen) | `IReceiptSpecificLogic` und 13 Implementierungen |
| K-19 | SwRS-024, SyRS-027 | Sperrmechanismen (pessimistisch `AssetLockBL` vs. optimistisch `ConcurrencyControlGuid`) | `InvoiceSpecificLogic.TryLockReceipt`; `ReceiptBase.ConcurrencyControlGuid` |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 17 (Lauf K)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:31+02:00
- **Endzeit:** 2026-08-25T20:36:06+02:00
- **Dauer gesamt:** 00:36:35 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:36:33 (`duration_ms`) — API: 00:33:43
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-2603`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 174
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.191 Input-/25 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 128 |
| Output-Tokens | 173.802 (davon 11.712 Thinking-Tokens) |
| Cache-Write-Tokens | 411.167 |
| Cache-Read-Tokens | 12.971.068 |
| Agent-Turns | 116 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 128 | 4.191 | 4.319 |
| Output-Tokens | 173.802 | 25 | 173.827 |
| Cache-Write-Tokens | 411.167 | 0 | 411.167 |
| Cache-Read-Tokens | 12.971.068 | 0 | 12.971.068 |
| Tokens gesamt | 13.556.165 | 4.216 | **13.560.381** |
**Tokens gesamt: 13.560.381** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `acecb691-99ee-4695-b41a-1d734db5d910`
- **Permission-Denials:** **0** – —
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 44.040 B | 15 Anforderungen |
| `SyRS.md` | 104.369 B | 32 Anforderungen |
| `SwRS.md` | 74.881 B | 24 Anforderungen |
| `Traceability.md` | 13.533 B | 49 Datenzeilen |
| `Hypothesen.md` | 15.981 B | 13 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 18.421 B | Domänenbegriffe |
| `Analysebericht.md` | 23.245 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **71 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 15 | 21,1 % |
| SyRS | 32 | 45,1 % |
| SwRS | 24 | 33,8 % |
| **Gesamt** | **71** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 14 | 19,7 % |
| Sicherheit | 14 | 19,7 % |
| funktional / Daten | 7 | 9,9 % |
| Daten | 4 | 5,6 % |
| Architektur | 3 | 4,2 % |
| funktional / Sicherheit | 2 | 2,8 % |
| funktional / Schnittstelle | 2 | 2,8 % |
| Sicherheit / rechtlich | 2 | 2,8 % |
| Sicherheit / Schnittstelle | 2 | 2,8 % |
| Daten / Architektur | 2 | 2,8 % |
| (18 weitere) | 19 | 26,8 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 277 |
| davon `PRIMÄR` | 174 (62,8 %) |
| davon `SEKUNDÄR` | 61 (22,0 %) |
| davon `KONTEXT` | 42 (15,2 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 71 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 18 | 25,4 % |
| Konsolidierungskandidaten | 25 | 35,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (35 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 71 von 71 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(174 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2023261,"num_turns":116,"stop_reason":"end_turn","session_id":"acecb691-99ee-4695-b41a-1d734db5d910","total_cost_usd":14.947209999999998,"usage":{"input_tokens":128,"cache_creation_input_tokens":411167,"cache_read_input_tokens":12971068,"output_tokens":173802,"output_tokens_details":{"thinking_tokens":11712},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":411167,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1566,"cache_read_input_tokens":410588,"cache_creation_input_tokens":579,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":579},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4191,"outputTokens":25,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004316,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":128,"outputTokens":173802,"cacheReadInputTokens":12971068,"cacheCreationInputTokens":411167,"webSearchRequests":0,"costUSD":14.942893999999999,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Alle sieben Ergebnisdateien sind erstellt; die Codebasis ist unverändert (`git status` leer).\n\n## Ergebnis\n\n**Ausgabeverzeichnis:** `01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\\Ergebnisse\\`\n\n| Datei | Zeilen | Inhalt |\n|---|---|---|\n| `StRS.md` | 661 | 15 Stakeholder-Anforderungen |\n| `SyRS.md` | 1493 | 32 Systemanforderungen (5 explizit ISO/IEC 25010 zugeordnet) |\n| `SwRS.md` | 1108 | 24 Softwareanforderungen |\n| `Traceability.md` | 149 | Haupttabelle, 2 Abdeckungsmatrizen, Redundanzregister K-01…K-19 |\n| `Hypothesen.md` | 325 | 11 offene Fragen mit fehlender Information |\n| `Glossar.md` | 404 | Domänenbegriffe mit Fundstellen |\n| `Analysebericht.md` | 382 | Modulübersicht, Konsistenzcheck, Selbstbewertung |\n\n**71 Anforderungen, 277 Artefaktbelege** (62,8 % `PRIMÄR`). Konsistenzcheck maschinell ausgeführt: keine doppelten IDs, keine Anforderung ohne `PRIMÄR`-Beleg, keine Tracelinks ins Leere, alle 12 Pflichtfelder in allen 71 Anforderungen belegt.\n\n**Methodische Entscheidung, die ich hervorheben möchte:** Ich habe *keine* Anforderung mit `Status: HYPOTHESE` formuliert. Stattdessen sind nur belegbare Aussagen in die Spezifikation gegangen; alles Unbelegbare steht als offene Frage in `Hypothesen.md`. Die Entwicklerdokumentation unter `docs/` habe ich durchgängig nur als `KONTEXT` gewertet — Grund ist ein nachgewiesener Widerspruch zum Code (dokumentiert sind vier Belegzustände, implementiert sind drei).\n\n**Inhaltlich auffällig** (alle in den Anforderungen belegt und als `Workaround` markiert):\n- `// TODO the password should be salted!!!` — Kennwörter als ungesalzener SHA-1 über Codepage 1252 (`SwRS-009`)\n- `HelpdeskCloseBL.CanCloseHelpdesk()` gibt unbedingt `true` zurück, während zwei andere Stellen dieselbe Prüfung tatsächlich implementieren (`SyRS-017`, K-02)\n- `DataSecurityExecuteCleanUp()` prüft Rechte und gibt danach Erfolg zurück, ohne zu löschen (`SyRS-025`, H-04)\n- Intervall→Monate dreifach implementiert, `Daily` jeweils unterschiedlich behandelt (`SwRS-022`, K-03)\n- Belege werden über Views gelesen, aber über Legacy-Repositories in deutsche Alttabellen geschrieben (`SwRS-003`, K-06)\n\n**Wichtigste Einschränkung, die ich klar benennen muss:** Die Fachbreite ist unvollständig. Bei 16 063 C#-Dateien habe ich risikobasiert priorisiert (Sicherheit, Berechtigungen, Fakturierung) — geschätzt **55–65 % des Fachumfangs sind nicht spezifiziert** (u. a. Lagerwirtschaft, Zahlungsverkehr, Produktion, CRM, Reportengine). Als Basis für eine Neuimplementierung reicht dieser Stand noch nicht; `Analysebericht.md` Abschnitt 6.5 priorisiert die Folge-Iterationen, wobei die 12 ungenutzten Testprojekte und die 799 Migrationsskripte (kein `.sql` im Repo, Schema entsteht nur zur Laufzeit) den größten Evidenzzuwachs bei geringstem Aufwand versprechen.","ttft_ms":1803,"ttft_stream_ms":1076,"time_to_request_ms":34,"type":"result","duration_ms":2192516,"uuid":"d3eea712-8437-4e46-acfb-62ff3dadcece","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 15 | 21,1 % |
| SyRS | 32 | 45,1 % |
| SwRS | 24 | 33,8 % |
| **Gesamt** | **71** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 14 | 19,7 % |
| Sicherheit | 14 | 19,7 % |
| funktional / Daten | 7 | 9,9 % |
| Daten | 4 | 5,6 % |
| Architektur | 3 | 4,2 % |
| funktional / Sicherheit | 2 | 2,8 % |
| funktional / Schnittstelle | 2 | 2,8 % |
| Sicherheit / rechtlich | 2 | 2,8 % |
| Sicherheit / Schnittstelle | 2 | 2,8 % |
| Daten / Architektur | 2 | 2,8 % |
| (18 weitere) | 19 | 26,8 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 277 |
| davon `PRIMÄR` | 174 (62,8 %) |
| davon `SEKUNDÄR` | 61 (22,0 %) |
| davon `KONTEXT` | 42 (15,2 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 71 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 18 | 25,4 % |
| Konsolidierungskandidaten | 25 | 35,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (35 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 71 von 71 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:36:06.3208537+02:00
@@ -0,0 +1 @@
2026-08-25T19:59:31.9715431+02:00
@@ -0,0 +1,320 @@
# Analysebericht
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Verfahren:** Reverse Requirements Engineering nach ISO/IEC/IEEE 29148:2018, Schritte 2–6
(Scope manuell vorgegeben, Validierung durch Fachexperten steht aus)
**Vorgehen:** ausschließlich statische Analyse, keine Ausführung, keine Änderung der Codebasis
**Erstellt:** 2026-08-25
---
## 1. Untersuchungsgegenstand
### 1.1 Kennzahlen der Codebasis
| Kennzahl | Wert | Quelle |
|---|---|---|
| Projekte in der Projektmappe | 44 (davon 12 Testprojekte) | `Centron.sln` |
| C#-Dateien (ohne `bin`/`obj`) | 14 782 | Dateisystemzählung |
| XAML-Dateien | 1 233 | Dateisystemzählung |
| Razor-Dateien | 491 | Dateisystemzählung |
| Testdateien (C#) | 378 | `tests/` |
| Datenbank-Migrationsskripte (C#-Klassen) | 764 | `…/Scripts/ScriptMethods/Scripts/` |
| Zusätzliche XML-Skriptsammlungen (Altbestand) | 7 | `…/Scripts/ScriptMethods/SqlStatements/` |
| Hintergrunddienste | 33 | `…/AspNetCore/HostedServices/` |
| Registrierte anmeldefähige Anwendungen | 43 | `ApplicationKind.cs` |
| Objektarten (`CentronObjectKindNumeric`) | über 230 | `CentronObjectKindNumeric.cs` |
| Nummernkreise | 31 | `NumberGroupEnum.cs` |
| Commits | 52 135 | `git rev-list --count HEAD` |
| Erster Commit | 29.07.2014 | `git log --reverse` |
| Aktuelle Produktversion | `2.0.2611-alpha` | `version.json` |
| Zielplattform | .NET 10 (`net10.0`, `net10.0-windows`) | `.csproj`, `global.json` |
### 1.2 Komponentenübersicht
| Komponente | Pfad | Rolle | Umfang |
|---|---|---|---|
| **Centron.Entities** | `src/backend/Centron.Entities` | Domänenentitäten (NHibernate) | 1 179 Dateien in `Entities` |
| **Centron.DAO** | `src/backend/Centron.DAO` | Mappings, Repositories, `DAOSession` | 983 Mapping-, 67 Repository-Dateien |
| **Centron.BL** | `src/backend/Centron.BL` | Geschäftslogik | 959 Dateien Administration, 464 WebServices, 248 Sales, 40 Warehousing u. a. |
| **Centron.Interfaces** | `src/backend/Centron.Interfaces` | Schichtübergreifende Verträge, Aufzählungen | 283 Sales, 53 Administration, 50 Warehousing u. a. |
| **Centron.Gateway** | `src/backend/Centron.Gateway` | Fremdformat-Parser (EDI) | 32 DataExchange, 26 EDI_EGIS |
| **Centron.Common / Centron.Core** | `src/backend/`, `src/shared/` | Technische Hilfsmittel, Kryptografie, Erweiterungen | 21 Extensions u. a. |
| **Centron.WebServices.Core** | `src/webservice/Centron.WebServices.Core` | DTOs, REST-Request-Typen, Rechtekonstanten | 1 725 Entities, 615 RestRequests, 162 „EntitiesWrongPlace" |
| **Centron.Host** | `src/webservice/Centron.Host` | Anwendungsserver (ASP.NET Core), Dienstfassade, Hintergrunddienste | 71 AspNetCore-, 67 Services-Dateien |
| **Centron.Host.Console / .WindowsService** | `src/webservice/` | Betriebsarten des Anwendungsservers | klein |
| **Centron.Controllers** | `src/webservice/Centron.Controllers` | REST-Controller | 41 Dateien |
| **Centron.WPF.UI** | `src/centron/Centron.WPF.UI` | Windows-Fachclient | 3 657 Modul-, 688 Service-, 94 Prozess-Dateien |
| **Centron.WPF.UI.Extension** | `src/centron/` | Client-Erweiterungen | 34 Actions, 29 Module |
| **Centron.Controls / .Preview** | `src/shared/` | Wiederverwendbare Oberflächenbausteine | 75 PositionGrid, 69 PasswordManager, 58 MyDay u. a. |
| **CentronNexus / .Host** | `src/nexus/` | Blazor-Webanwendung („c-entron Web") | 136 Shared-, 94 ServiceBoard-Dateien; 491 Razor-Komponenten |
| **CentronNexus.OutlookAddIn** | `src/nexus/` | Outlook-Erweiterung | 22 Model-Dateien |
| **APIs** | `src/apis/` | Fremdsystemanbindungen: EbInterface, GLS, Shipcloud, COP, EGIS, finAPI, Icecat, ITscope | 56 FinAPI-, 23 Shipcloud-Dateien |
| **Deployment / Docker / CI** | `deployment/`, `docker/`, `azure/`, `.github/` | Installationspakete (WiX), Container, Pipelines | 4 Workflows, 6 Pipelines, 7 Vorlagen |
### 1.3 Fachliche Modulstruktur des Windows-Clients
Gemessen an der Zahl der C#/XAML-Dateien je Modulordner unter
`src/centron/Centron.WPF.UI/Modules`:
| Modul | Dateien | Modul | Dateien |
|---|---|---|---|
| Finances | 2 142 | Survey | 64 |
| Warehousing | 529 | Massenupdates | 48 |
| Administration | 327 | Sales | 42 |
| Helpdesk | 316 | Rma | 33 |
| DataExchange | 224 | PasswordManager | 29 |
| MyCentron | 211 | Production | 28 |
| Statistics | 141 | ProjectPriceImport | 19 |
| Purchasing | 136 | Calendar | 18 |
| Global | 111 | Reports | 10 |
| OnlineBanking | 88 | PayersAndCostCenter, TelekomDive, ProjectManagement | je 9 |
| ArtificialIntelligence | 68 | QM, PLM, Logistic | je 8 |
Die Verteilung zeigt, dass der Schwerpunkt des Systems eindeutig im Bereich **Finanzen/Belegwesen**
liegt (2 142 von 3 657 Dateien, rund 59 %). Die Analysetiefe wurde entsprechend gewichtet.
---
## 2. Abgedeckte Bereiche und Analysetiefe
Die Analyse folgte einer risikobasierten Priorisierung: Bereiche mit Auswirkung auf
**Sicherheit, Fakturierung/Abrechnung und Berechtigungen** wurden vertieft im Quelltext gelesen,
strukturelle und periphere Bereiche stichprobenhaft.
**Legende:** ● vertieft (zentrale Klassen vollständig oder in den maßgeblichen Abschnitten
gelesen) · ◐ stichprobenhaft (Signaturen, Schlüsselstellen, Struktur) · ○ nicht analysiert
| Bereich | Tiefe | Gelesene Schlüsselartefakte | Abgeleitete Anforderungen |
|---|---|---|---|
| Authentifizierung und Sitzungsverwaltung | ● | `Authenticator.cs`, `BasicAuthenticator.cs`, `AuthenticatorFactory.cs`, `TicketBL.cs`, `TicketAuthenticationHandler.cs`, `AuthenticateInterceptor.cs` | SyRS-001…010, SwRS-022…027 |
| Berechtigungen | ● | `AppRightsBL.cs` (vollständig), `UserRightsConst.cs` (Struktur + Belegblöcke), `WebAccountRightsConst.cs`, `CentronRights.md` | SyRS-011…013, SwRS-015…019 |
| Lizenzierung | ● | `LicenseManager.cs` (vollständig), `ApplicationKind.cs` (vollständig), `AccessTokenBL.cs` (Schlüsselstellen) | SyRS-007…009, SwRS-020, -021, -025 |
| Belegverarbeitung (Kern) | ● | `ReceiptBL.cs` (Speicherpfad, Rechteprüfung, Nummernvergabe, Zahlung, Protokollierung – ca. 900 von 13 000 Zeilen gezielt gelesen), `ReceiptBase.cs`, `ReceiptState.cs`, `ReceiptWebServiceBL.cs` (Schlüsselstellen) | SyRS-014…018, SwRS-004, -009, -012…015 |
| Nummernkreise | ● | `NumberGroupBL.cs` (vollständig), `NumberGroupEnum.cs` (vollständig) | SyRS-015, SwRS-010, -011 |
| Steuer- und Preisfindung | ● | `TaxBL.cs` (vollständig), `ReceiptItemPriceBL.cs` (Preisfindungskaskade) | SyRS-020, -021, SwRS-028, -029 |
| Lagerbuchung | ● | `ReceiptArticleBookingBL.cs` (Buchungspfad) | SyRS-019, SwRS-030, -031 |
| Helpdesk | ● | `HelpdeskBL.cs` (Speicher- und Rechtepfad), `HelpdeskCompact.cs` (vollständig) | SyRS-035, -036, SwRS-043, -044 |
| Verträge und automatische Abrechnung | ◐ | `AutomaticFacturaBL.Contracts.cs` (Selektions- und Markierungslogik, Methodenverzeichnis), `contracts-backend.md` | StRS-007, SyRS-022, SwRS-032 |
| Mahnwesen | ◐ | `DunningBL.cs` (Aggregation, Filter, Mahnstopp) | StRS-013, SyRS-037, SwRS-033 |
| E-Rechnung (ZUGFeRD/XRechnung) | ◐ | `InvoiceZugferdBL.cs` (Formatabbildung, Guideline-IDs), `ZugferdKind.cs` (vollständig) | StRS-011, SyRS-023, SwRS-045 |
| EDI | ◐ | Dateistruktur `SupplierEdiBL.*`, `edi-architecture.md` | StRS-014, SyRS-024, SwRS-046 |
| DSGVO / Datenschutz | ◐ | `DataSecurityBL.cs` (Methodenverzeichnis, Löschpfade, Konstanten) | StRS-016, SyRS-038, SwRS-047 |
| Hintergrunddienste und Betrieb | ● | `ManagedBackgroundService.cs` (vollständig), `DataQualityService.cs` (Kopf), Intervalle aller 33 Dienste | StRS-018, SyRS-025, -026, SwRS-034, -035 |
| Datenbankmigration | ● | `ScriptEngineBL.cs` (Kernalgorithmus), `ScriptMethod11803.cs` (vollständig), `create-scripts.md`, `database-conventions.md` | SyRS-027, SwRS-036, -037 |
| Konfiguration und Deployment | ● | `WebServiceConfigSerializer.cs`, `WebServiceConfig.xml`, `compose.yaml`, `appsettings.Production.json`, `Directory.Build.props`, `version.json` | SyRS-032, -033, -040, SwRS-039, -048, -049 |
| Webanwendung Nexus | ◐ | `AuthService.cs`, `PortAuthorization.cs`, Verzeichnis `Shared/Authorization`, Struktur der Razor-Komponenten | StRS-003, SyRS-034, SwRS-041, -042 |
| Windows-Fachclient | ◐ | `ModuleRegistration.cs` (Importliste, Registrierungsmuster), Modulverzeichnisstruktur | SwRS-040 |
| Buchhaltungsexport / DATEV | ◐ | `BookKeepingExportBL.cs` (Methodensignaturen) | StRS-012 |
| Online-Banking / finAPI | ◐ | `FinApiConstants.cs`, `RestClientBase.cs` (OAuth), Verzeichnisstruktur | StRS-020 |
| RMA | ◐ | `ReceiptBL.CheckCloseRMADeliverylistReceipt`, Nummernkreise, Objektarten | StRS-023 |
| Provision | ◐ | Entitätenliste, `FillReceiptWithProvision`, Hintergrunddienst | StRS-022 |
| Reporting / PDF-Ablage | ◐ | `ReceiptBL.AddReportPdf`, FastReport-Referenzen | StRS-021, SyRS-039 |
| Test- und CI-Infrastruktur | ◐ | Verzeichnis `tests/`, `.github/workflows/`, `azure/` | SwRS-050 |
| Statistik / Auswertung | ○ | – | – |
| Passwortmanager | ○ | – | – |
| Telefonie / TAPI / Communicator | ○ | – | – |
| Künstliche Intelligenz (Chat, Zusammenfassung) | ○ | – | – |
| MyDay / Zeitwirtschaft (eigenständig) | ○ | – | – |
| Produktion, PLM, QM, Logistik, Kommissionierung | ○ | – | – |
| Survey / Kampagnen / CRM-Projekte | ○ | – | – |
| Outlook-Add-In, Exchange-/Graph-Synchronisation | ○ | – | – |
| Fremd-APIs: GLS, Shipcloud, Icecat, ITscope, COP, docuFORM, EbInterface | ○ | – | – |
| Inventur, Seriennummern-/Barcodeverwaltung im Detail | ○ | – | – |
| Berichtswesen (Reportdefinitionen, ReportEngine) | ○ | – | – |
---
## 3. Ergebnis des Konsistenzchecks
Der Check wurde maschinell über alle drei Spezifikationsdateien ausgeführt (Extraktion aller
`ID:`-Zeilen, aller `Tracelinks:`- und `Konsolidierung:`-Referenzen sowie aller Belegmarkierungen).
| Prüfpunkt | Ergebnis |
|---|---|
| Anzahl Anforderungen gesamt | **119** (StRS 25, SyRS 43, SwRS 51) |
| Doppelte oder mehrfach vergebene IDs | **keine** |
| Anforderungen ohne Beleg | **keine** – jede der 119 Anforderungen führt mindestens einen Beleg |
| Anforderungen ohne `PRIMÄR`-Beleg | **keine** – jede der 119 Anforderungen führt mindestens einen `PRIMÄR`-Beleg |
| Tracelinks auf nicht existierende IDs | **keine** |
| SwRS-Anforderungen ohne Verweis auf eine SyRS-Anforderung | **keine** |
| SyRS-Anforderungen ohne Verweis auf eine StRS-Anforderung | **keine** |
### 3.1 Belegverteilung
| Ebene | Anforderungen | `PRIMÄR` | `SEKUNDÄR` | `KONTEXT` | Anteil `PRIMÄR` |
|---|---|---|---|---|---|
| StRS | 25 | 66 | 16 | 15 | 68,0 % |
| SyRS | 43 | 99 | 18 | 18 | 73,3 % |
| SwRS | 51 | 106 | 3 | 37 | 72,6 % |
| **Gesamt** | **119** | **271** | **37** | **70** | **71,7 %** |
Die risikobasierte Priorisierung wurde eingehalten: Alle Anforderungen zu Sicherheitsregeln
(SyRS-001…013, -029…034, SwRS-015…027, -039, -041, -042, -047), zur Abrechnungs- und
Fakturierungslogik (SyRS-014…023, -037, SwRS-028…033, -045) und zu Berechtigungen führen
mindestens einen `PRIMÄR`-Beleg. Keine Anforderung dieser Kategorien musste als `[HYPOTHESE]`
gekennzeichnet werden.
### 3.2 Weitere Kennzahlen
| Merkmal | Anzahl |
|---|---|
| Anforderungen mit `Status: … Workaround` (historischer Sonderfall / bekannte Altlast) | 29 |
| Anforderungen mit `[HYPOTHESE]`-markierter Teilaussage | 7 |
| Dokumentierte Konsolidierungskandidaten (Feld `Konsolidierung`) | 30 Einzelvermerke, verdichtet zu **19 Kandidaten** (K-01…K-19 in `Traceability.md`) |
| Hypothesen mit offener Frage (`Hypothesen.md`) | 12 |
---
## 4. Widersprüche zwischen Artefakten
Die Entwicklerdokumentation unter `docs/` wurde durchgängig als `KONTEXT` klassifiziert. Der
Grund ist ein nachweisbarer inhaltlicher Widerspruch zum Code:
| # | Widerspruch | Dokumentation | Code | Bewertung |
|---|---|---|---|---|
| W-01 | Belegzustandsmodell | `docs/reference/receipts/receipts-backend-architecture.md:284-290` nennt vier Zustände: „Draft – Released – Processed – Cancelled" | `ReceiptState` definiert drei Zustände: `Active` (offen), `Completed` (abgeschlossen), `Canceled` (storniert) | Code maßgeblich; siehe HYP-009 |
| W-02 | Verbindlichkeit der Schichtenarchitektur | `docs/getting-started/general-structure.md:3` räumt selbst ein: „there are tons of places where this general structure does not apply" | – | Die Sollarchitektur ist nicht flächendeckend umgesetzt; für die Migration ist von Abweichungen auszugehen |
| W-03 | Zentraler Rechtekonstantenkatalog | `docs/guides/development/check-userrights.md:5-6`: „Always use these constants instead of the id itself." | `ApplicationKind.cs:56-62` dupliziert vier Rechte-IDs als lokale Konstanten mit dem Kommentar „// Taken from UserRightsConst"; `AppRightsBL.GetAssignableAdminRightI3Ds()` führt 34 Zahlliterale | Regel wird im Bestand verletzt |
| W-04 | Lizenzkatalog als Wahrheitsquelle | `docs/reference/security/licensing-system.md:32-35`: „The single source of truth … is the license-server. We **try** to keep the `LicenseGuids.cs` file in sync" | `LicenseGuids.cs` ist eine manuell gepflegte Kopie | Der Katalog kann vom Lizenzserver abweichen |
---
## 5. Bekannte Lücken
### 5.1 Lücken in der Traceability
Drei StRS-Anforderungen besitzen keine korrespondierende SwRS-Anforderung, weil die zugehörige
Implementierung nur oberflächlich analysiert wurde:
| StRS | Thema | Fehlende SwRS-Ebene | Erforderlicher Nachschlag |
|---|---|---|---|
| StRS-021 | Belegdruck und PDF-Ablage | Reportengine, Reportdefinitionen, Dateinamensvariablen | `ReportDataBL` (92 KB), `PdfExportFilenameReplacementBL`, `Centron.Controls/Reports` (50 Dateien) |
| StRS-022 | Provisionsermittlung | Berechnungsalgorithmus je Schema und Stufe | `ReceiptProvisionBL` (45 KB) |
| — (SyRS-043) | Telemetrie | Konkrete Nutzdaten und Abschaltbarkeit | `TelemetryAggregator`, `HttpTelemetryUploadClient` |
### 5.2 Nicht verfügbare Artefaktklassen
| Fehlendes Artefakt | Auswirkung |
|---|---|
| **Datenbankschema-Abzug** (Tabellen, Spalten, Typen, Constraints, Indizes) | Das Datenmodell konnte nur indirekt über Entitäten, Mappings, Migrationsskripte und die Entwicklerdokumentation rekonstruiert werden. Dies ist die Hauptursache für die verbliebenen `KONTEXT`-Belege im Datenmodellbereich (siehe HYP-012). |
| **Ticketsystem / Anforderungsdokumente** | Commit-Messages verweisen systematisch auf Ticketnummern (z. B. „Ticket 168496", „Ticket 160276", „Ticket 124919"), die Tickets selbst liegen nicht vor. Fachliche Begründungen von Sonderfällen bleiben daher unbelegt. |
| **Release Notes / Migrationsnotizen** | Nicht im Arbeitsverzeichnis vorhanden. Die Versionshistorie ist nur über `version.json`, die Git-Historie (52 135 Commits seit 2014) und die `ApplicationVersion`-Angaben der 764 Migrationsskripte rekonstruierbar. |
| **Report- und Formulardefinitionen** | FastReport-Definitionen liegen nicht als lesbare Dateien im Repository; Belegdruckbilder konnten nicht ausgewertet werden. |
| **Betriebs- und Lastdaten** | Keine Aussagen zu realen Antwortzeiten, Datenvolumina oder Nutzerzahlen möglich; die nicht-funktionalen Anforderungen zur Performanz beschränken sich daher auf im Code verankerte Größen (Intervalle, Blockgrößen, Cache-Zeiten). |
### 5.3 Bewusst nicht erfasste Bereiche
Die in Abschnitt 2 mit ○ markierten Bereiche wurden nicht analysiert. Der größte
Einzelblock ist `Statistics` (141 UI-Dateien, `ContractEvaluationBL` 87 KB, `MspCollectorsBL`
70 KB, `Centron.BL/Statistics` 16 Dateien); der zweitgrößte der Passwortmanager
(`Centron.Controls/PasswordManager` 69 Dateien, `Modules/PasswordManager` 29 Dateien,
eigene Lizenz `LicenseGuids.PasswordManager`, eigener Rechtebereich).
---
## 6. Selbstbewertung
### 6.1 Vollständigkeit der Analyse
**Vollständig analysiert** (zentrale Klassen in den maßgeblichen Teilen gelesen, Aussagen
durchgängig `PRIMÄR` belegt):
Authentifizierung, Sitzungsverwaltung, Berechtigungen, Lizenzierung, Nummernkreise,
Steuersatzermittlung, Belegzustands- und Versionsmodell, Belegrechteprüfung, Lagerbuchung,
Helpdesk-Rechte- und Speicherpfad, Hintergrunddienst-Rahmenwerk, Datenbankmigration,
Betriebskonfiguration und Bauvorgaben.
**Stichprobenhaft analysiert** (Struktur, Signaturen und Schlüsselstellen gelesen; die
Anforderungen beschreiben das Verfahren korrekt, aber nicht erschöpfend):
Vertragsabrechnung, Mahnwesen, E-Rechnung, EDI, DSGVO, Nexus-Webanwendung, Windows-Fachclient,
Buchhaltungsexport, Online-Banking, RMA, Provision, Reporting, Testinfrastruktur.
**Nicht analysiert:** siehe Abschnitt 2 (○-Zeilen) und HYP-001.
Belastbare Schätzung des Abdeckungsgrads: Die 119 Anforderungen decken die
**architektur- und sicherheitsprägenden Mechanismen weitgehend vollständig** ab, die
**fachliche Breite** jedoch nur zu einem geschätzten Drittel. Insbesondere fehlen die
Auswertungs- und Statistiklogik sowie mehrere eigenständige Fachmodule.
### 6.2 Stellen mit dünner Beleglage
Der Anteil von `PRIMÄR`-Belegen liegt insgesamt bei 71,7 %. Die folgenden 20 Anforderungen
stützen sich auf genau einen `PRIMÄR`-Beleg und sollten in einer Folge-Iteration verstärkt werden:
| Anforderung | Beleglage | Grund |
|---|---|---|
| StRS-012 (Buchhaltungsübergabe) | 1 × PRIMÄR, 1 × SEKUNDÄR | `BookKeepingExportBL` (81 KB) nur über Methodensignaturen erfasst |
| SwRS-005 (Objekttypschlüssel) | 1 × PRIMÄR, 3 × KONTEXT | Die Aussage stützt sich stark auf Quelltextkommentare |
| SwRS-007 (Versionstabellen) | 1 × PRIMÄR, 1 × KONTEXT | Nur ein Migrationsskript als Nachweis; kein Schemaabzug (HYP-012) |
| SwRS-002 (Doppelimplementierung) | 1 × PRIMÄR, 1 × KONTEXT | Die Verbindlichkeit stammt aus der Dokumentation (HYP-006) |
| SwRS-035 (Datenqualitätsaufgaben) | 1 × PRIMÄR, 1 × KONTEXT | Aufgaben 4–9 nur dokumentiert (HYP-008) |
| SyRS-010, -021, -026, -028, -033, -039; SwRS-011, -012, -013, -020, -025, -031, -037, -043; SyRS-005 | je 1 × PRIMÄR | ausreichend für die Kernaussage, aber ohne Bestätigung durch einen zweiten Fundort |
Bereiche mit auffällig hohem `KONTEXT`-Anteil: **Datenmodell und Schemastruktur**
(SwRS-005, -006, -007, -008) sowie **EDI** (SwRS-046, SyRS-024). In beiden Fällen ist die
Ursache dieselbe: Es fehlen maschinenlesbare Strukturartefakte (Schemaabzug, EDI-Beispieldateien).
Der `SEKUNDÄR`-Anteil ist auf SwRS-Ebene mit 3 Belegen (2,1 %) auffällig niedrig. Das ist
plausibel, weil UI-Texte und Konfigurationsschalter fachliche Aussagen auf StRS-/SyRS-Ebene
tragen, während die SwRS-Ebene definitionsgemäß Codeeigenschaften beschreibt.
### 6.3 Migrationsrelevante Befunde (Priorisierung für die Validierung)
Die 29 als `Workaround` gekennzeichneten Anforderungen sind die Arbeitsliste für die
Fachvalidierung. Die aus meiner Sicht kritischsten sieben:
| Rang | Befund | Anforderung | Warum kritisch |
|---|---|---|---|
| 1 | **Kennwörter als ungesalzenes SHA-1** – im Quelltext selbst als `// TODO the password should be salted!!!` markiert | SyRS-004, SwRS-024 | Identische Kennwörter erzeugen identische Hashwerte; für ein SaaS-Zielsystem nicht tragbar. Die Migration erfordert einen Neuvergabe- oder Rehash-bei-Anmeldung-Pfad. |
| 2 | **DSGVO-Löschung unvollständig** – `DoDeleteCustomer`, `DoDeleteSupplier`, `DoDeleteAccount` werfen `NotImplementedException` | StRS-016, SyRS-038, SwRS-047 | Compliance-Lücke mit rechtlicher Wirkung; die vorgesehenen SQL-Anweisungen liegen nur auskommentiert vor. |
| 3 | **Zwei Persistenzpfade für Belege** (NHibernate-Entität + Legacy-Repository auf Alttabellen) | SwRS-006, SwRS-008 | Laut Architekturdokumentation eine bekannte Fehlerquelle („value may load correctly from the view but will not be persisted on save"). Für die Neuimplementierung ist ein bereinigtes Schema Voraussetzung. |
| 4 | **Klartextpfad für Verbindungsgeheimnisse** (`DatabaseConnectionStringPlain`) und mitgelieferte Beispielschlüssel (`SecretKey` identisch in zwei Auslieferungsdateien) | SyRS-032, SwRS-039 | Betriebsrisiko; zusätzlich sind Zertifikatspasswort und Signaturschlüssel gar nicht verschlüsselt. |
| 5 | **Doppelbuchungsschutz als Symptombehandlung** – Kommentar zu Ticket 124919: „We cant reproduce this issue" | SwRS-031 | Eine ungeklärte Bestandsverfälschung darf nicht in ein Zielsystem übernommen werden; die Ursache ist vor der Migration zu klären. |
| 6 | **Sicherheit ist Opt-in** – eine Dienstmethode ohne `AuthenticateAttribute` ist unauthentifiziert erreichbar | SwRS-027 | Im Zielsystem ist „sicher per Voreinstellung" (Opt-out) zu wählen. |
| 7 | **`EnableUnsafeBinaryFormatterSerialization` und Unterdrückung von NuGet-Schwachstellenwarnungen** | SwRS-049 | Bewusst akzeptierte Risiken, die eine Neuimplementierung nicht fortschreiben sollte. |
### 6.4 Empfehlungen für eine Folge-Iteration
Nach Wirkung geordnet:
1. **Datenbankschema-Abzug bereitstellen und einlesen.** Dies ist die wirkungsvollste
Einzelmaßnahme: Sie ersetzt den Großteil der `KONTEXT`-Belege im Datenmodellbereich durch
`PRIMÄR`-Belege und klärt HYP-012 vollständig. Ohne Schema bleibt die Datenspezifikation für
eine Neuimplementierung unvollständig.
2. **Fachliche Breite nachziehen.** Schwerpunkte: `Statistics` (Auswertungslogik,
Vertragsbewertung, MSP-Collector), Passwortmanager, MyDay/Zeitwirtschaft, Kommissionierung
und Inventur. Diese Bereiche tragen eigenständige Geschäftsregeln, die bisher fehlen.
3. **`ReceiptBL` vollständig erschließen.** Die Klasse umfasst 609 KB (über 13 000 Zeilen);
in diesem Lauf wurden gezielt rund 900 Zeilen gelesen. Alle nicht gelesenen Abschnitte sind
potenzielle Quellen weiterer Geschäftsregeln – insbesondere Belegweiterführung, Kopieren,
Frachtartikel, Kundenrabattpositionen, Excel-Export und Mailversand.
4. **Positionsebene der Belege erfassen.** `ReceiptItemBL` (225 KB) und `ReceiptItemTimerBL`
(104 KB) wurden nicht gelesen. Positionslogik (Mengen, Preise, Rabatte, Verknüpfung mit
Zeiterfassung) ist für ein Zielsystem mindestens so wichtig wie die Kopflogik.
5. **Rechte vollständig katalogisieren.** `UserRightsConst.cs` enthält über 60 verschachtelte
Klassen; in diesem Lauf wurden die Belegblöcke und einzelne Bereiche gelesen. Ein
vollständiger, maschinell extrahierter Rechtekatalog mit Zuordnung zu den prüfenden
Codestellen wäre für das Zielsystem unmittelbar verwertbar.
6. **Offene Fragen HYP-004, HYP-010, HYP-011 klären.** Alle drei betreffen Integrität
(fakturierte Zeiten, Wirksamkeit des Rechteentzugs, Datenverlust bei Nebenläufigkeit) und sind
mit begrenztem Leseaufwand entscheidbar.
7. **Testbestand als Anforderungsquelle nutzen.** Die 378 Testdateien – insbesondere
`Centron.Tests.EndToEnd` und `Centron.Tests.Integration` – enthalten ausführbare
Sollaussagen. Sie sind eine bisher ungenutzte `PRIMÄR`-Belegquelle und eignen sich
besonders zur Bestätigung von Geschäftsregeln, die aus Implementierungscode nur
interpretativ ableitbar sind.
### 6.5 Einschränkungen dieses Laufs
- Die Analyse erfolgte **rein statisch**. Kein Programmteil wurde ausgeführt, keine Datenbank
angebunden, kein Test ausgeführt. Alle Prüfideen sind Vorschläge, keine Nachweise.
- Die Codebasis wurde **ausschließlich gelesen** und nicht verändert; dies wurde durch die
Beschränkung auf lesende Werkzeuge sichergestellt.
- Textsuchen über die gesamte Codebasis liefen mehrfach in eine Zeitüberschreitung und mussten
auf Teilverzeichnisse eingegrenzt werden. Es ist daher möglich, dass Fundstellen außerhalb der
durchsuchten Verzeichnisse übersehen wurden. Wo eine Aussage auf Vollständigkeit angewiesen
ist (z. B. „an sieben Stellen kopiert"), bezieht sie sich auf das jeweils genannte
Suchverzeichnis.
- Angaben zu Zeilennummern beziehen sich auf den Stand des Commits `79c1142f48`
(25.08.2026, „Versuchsbasis: KI-Assistenz-Konfigurationen entfernt").
@@ -0,0 +1,119 @@
# Glossar
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Zweck:** Definition aller Domänenbegriffe, die in `StRS.md`, `SyRS.md` und `SwRS.md` verwendet
werden. Jeder Begriff nennt die technische Entsprechung in der Codebasis, damit die Zuordnung
zwischen fachlicher Aussage und Artefakt eindeutig bleibt.
Spalte **Beleg** verweist auf das Artefakt, aus dem die Definition abgeleitet ist.
---
## 1. Kernbegriffe des Belegwesens
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Beleg** | Kaufmännisches Dokument mit Kopfdaten und Positionen, das einen Geschäftsvorfall zwischen dem Betreiber und einem Kunden oder Lieferanten dokumentiert. Kundenbelege und Lieferantenbelege werden unterschieden. | `ReceiptBase` (abstrakt), `IReceiptBase` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9` |
| **Belegart** | Fachliche Klasse eines Belegs (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag, Anfrage, Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift). | `CentronObjectKindNumeric` mit `IsCustomerReceipt()` / `IsSupplierReceipt()` | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:268-301` |
| **Belegkopf** | Kopfdatensatz eines Belegs (Nummer, Datum, Empfänger, Adressen, Währung, Zustand). Physisch in Tabellen mit der Endung `Kopf`. | `AngKopf`, `AufKopf`, `LiefKopf`, `RechKopf`, `VertragKopf`, `GutKopf`, `AbholKopf` | `src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:78-137` |
| **Belegposition** | Einzelne Zeile eines Belegs (Artikel, Text, Rabatt, Fracht). Physisch in Tabellen mit der Endung `Pos`. | `AngPos`, `AufPos`, `LiefPos`, `RechPos`, `VertragPos`, `GutPos`, `AbholPos`; Entität `ReceiptItemBase` | `docs/reference/receipts/receipts-backend-architecture.md:74-82` |
| **Positionsart** | Typ einer Belegposition; bestimmt insbesondere, ob eine Lagerbuchung erfolgt. | `ReceiptItemKind` (u. a. `Article`, `CustomerDiscount`, `SupplierFreightNoSplitArticle`, `SupplierInsuranceNoSplitArticle`) | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:174-177` |
| **Belegzustand** | Fachlicher Bearbeitungsstand eines Belegs: *offen*, *abgeschlossen*, *storniert*. | `ReceiptState.Active = 1`, `Completed = 2`, `Canceled = 3` | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-14` |
| **Belegversion** | Fortlaufende Nummer einer inhaltlichen Belegfassung. Jede neue Version archiviert den Vorzustand vollständig. | `ReceiptBase.Version`, Versionstabellen `*KopfVersions` / `*PosVersions` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578` |
| **Belegvorlage** | Beleg, der nicht Teil des produktiven Geschäftsvorfalls ist, sondern als Muster dient. Erkennbar an negativer Belegnummer und Zuordnung zum konfigurierten Vorlagenkunden. | `ReceiptBase.IsTemplate => Number < 0`, `ReceiptTemplateBL` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:65` |
| **Belegweiterführung** | Erzeugung eines Folgebelegs aus einem oder mehreren Vorgängerbelegen unter Übernahme von Positionen (z. B. Auftrag → Lieferschein). | `ReceiptWebServiceBL.ForwardReceipt`, `CanForwardReceiptsInto` | `…/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2315-2336` |
| **Verarbeitete Menge** | Anteil der Positionsmenge, der bereits in einen Folgebeleg übernommen wurde. Steuert gemeinsam mit der Gesamtmenge die Lagerbuchung. | `IReceiptItemBase.QuantityProcessed`, `QuantityComplete` | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:191-193` |
| **Belegempfänger** | Adressblock eines Belegs. Es werden bis zu vier Empfänger geführt: Standard-, Rechnungs-, Liefer- und Lizenznehmeradresse. | `ReceiptReceiver`, `ReceiptReceiverInvoice`, `ReceiptReceiverDelivery`, `ReceiptReceiverLicense` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:58-61` |
| **Nummernkreis** | Konfigurierbarer Zähler je Belegart, Mandant und Filiale mit Startwert, Schrittweite und Wertebereich. | Entität `NumberGroup`, Aufzählung `NumberGroupEnum` (31 Werte) | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:50-134` |
| **Nebenläufigkeitskennzeichen** | GUID, die bei jeder Belegänderung neu gesetzt wird und beim Schreiben gegen den vom Client mitgeführten Wert geprüft wird (optimistische Sperre). | `ReceiptBase.ConcurrencyControlGuid`, Datenbankspalte `GUI3D` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4939-4940` |
| **Belegsperre** | Pessimistische, benutzerbezogene Sperre eines Belegs während der Bearbeitung. | `TryLockReceipt`, `UnLockReceipt` über `SpecificLogics` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3087-3093, 3166-3174` |
## 2. Stammdaten und Organisation
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Mandant** | Rechtliche Einheit, für die Belege geführt werden. Genau ein Mandant ist als Standard gekennzeichnet. | Entität `Mandator` (`Default == 1`), `CentronObjectKindNumeric.Company = 53` | `src/backend/Centron.BL/Administration/Company/MandatorBL.cs:19-22` |
| **Filiale** | Organisatorische Untereinheit eines Mandanten mit eigenen Nummernkreisen und eigenem Sichtbarkeitsbereich. | `BranchI3D`, `BranchBL`, `CentronObjectKindNumeric.Branch = 124` | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152` |
| **Standardfiliale** | Zustand „keine Filiale zugeordnet". Wird technisch sowohl als `NULL` als auch als `0` dargestellt; beide gelten als gleichwertig. | `BranchBL.IsBranchEqual`, Prüfung in `CanUserCreateReceiptsInBranch` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10258-10267` |
| **Kunde** | Geschäftspartner auf der Absatzseite. Es existieren zwei Datenstrukturen: die Alttabelle `Kunden` und die neuere `Account`-Struktur. | `CentronObjectKindNumeric.Customer = 12`, `CustomerClass = 5000012`, `Account = 7600071` | `…/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2372-2392` |
| **Lieferant / Kreditor** | Geschäftspartner auf der Beschaffungsseite. | Tabelle `Kreditor`, `CentronObjectKindNumeric.Creditor = 20` | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:124-131` |
| **Artikel** | Verkaufs- oder Beschaffungsgegenstand mit Artikelcode, Warengruppe, Steuersatz und Preisen. | Entitäten `Article`, `ArticleLight`, Tabelle `Artik`, `CentronObjectKindNumeric.Article = 9` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:246-275` |
| **Warengruppe / Sekundär-Warengruppe** | Zweistufige Klassifikation von Artikeln; dient unter anderem als Fallback für die Steuersatzermittlung. | `MaterialGroup = 70`, `SecondaryMaterialGroup = 136`, `MaterialGroupBL` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:257-273` |
| **Lager** | Bestandsführender Ort. Es wird zwischen Hauptlager (kein bzw. Kennung −1) und Nebenlagern unterschieden. | Entität `Stock`, `StockBL`, `SecondStockArticleBL` | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:136` |
| **Mitarbeiter** | Person im Unternehmen des Betreibers; Grundlage für Benutzerkonto, Filialzuordnung, Zeiterfassung und Provision. | `EmployeeCompact`, Tabelle `Personal`, `CentronObjectKindNumeric.EmployeeClass = 215` | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:206` |
## 3. Benutzer, Rechte und Lizenzen
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Benutzer (interner Benutzer)** | Anmeldekonto eines Mitarbeiters am ERP-System. | Entität `AppUser`, Tabelle `Sichbenu` | `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:49-50` |
| **Web-Account** | Anmeldekonto eines Endkunden für Selbstbedienungsfunktionen; besitzt ein eigenes, disjunktes Rechtemodell. | Entität `WebAccount`, Tabellen `WebAccounts`, `WebAccountsRights` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:679-691` |
| **Rechtegruppe** | Bündel von Rechten. Rechte werden ausschließlich über Gruppen an Benutzer vergeben. | Entität `AppGroup`, Tabelle `Sichgrup` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48` |
| **Recht** | Einzelne, numerisch identifizierte Berechtigung für eine fachliche Funktion. | Entität `AppRight`, Tabelle `Sichtrus` (Zuordnung Gruppe→Recht), Konstantenkatalog `UserRightsConst` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:653-656` |
| **Einschränkendes Recht** | Recht mit umgekehrter Wirkung: Sein *Besitz* verkleinert den Zugriffsbereich (z. B. „nur eigene", „nur eigene Filiale"). | z. B. `SHOW_OFFERS_ONLY_OWN`, `SHOW_HELPDESK_ONLY_OWN_BRANCH` | `CentronRights.md:9-17`; `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10284-10292` |
| **Ausschließendes Recht** | Recht, dessen Besitz die Anmeldung an einer bestimmten Anwendung *verhindert*. | `ApplicationKind.DisallowingRight`, z. B. `RIGHT_DISALLOW_SERVICEBOARD_LOGIN` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45, 60` |
| **Anwendung (ApplicationKind)** | Am Anwendungsserver anmeldefähiges Produkt mit eigener Lizenz-GUID, Ticketlebensdauer und Lizenzzählweise. | `ApplicationKind` (43 registrierte Instanzen) | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| **Lizenz** | GUID-identifiziertes Nutzungsrecht mit optionaler Anzahl, Ablaufdatum und maximaler Programmversion. | `LicenseGuids`, `LicenseManager.CheckLicense`, `GetLicenseCount` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302` |
| **Lizenzzählweise** | Regel, ob eine Lizenz je Benutzer oder je Benutzer und Gerät verbraucht wird. | `LicenseUsageKind.PerUser`, `PerUserAndPerMachine` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:173-177` |
| **Ticket (Sitzungsticket)** | Serverseitig geführter Sitzungsnachweis, gebunden an Anwendung, Benutzer bzw. Web-Account und Gerät, mit Ablaufzeitpunkt. **Nicht zu verwechseln mit dem Helpdesk-Ticket.** | Entität `Ticket` (Namensraum `Centron.Data.Entities.Ticketing`), `TicketBL`, `TicketRepository` | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:61-94` |
| **Access Token** | Persönlicher, lizenzpflichtiger Langzeittoken für Maschinen-zu-Maschinen-Zugriffe; nur der SHA-256-Hash wird gespeichert. | Entität `AccessToken`, `AccessTokenBL`, `AccessTokenLogBL` | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:154-186, 477-483` |
## 4. Vertrieb, Preise und Steuern
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Sonderpreis (Kunde)** | Kundenindividuelle Preiskondition mit fünf Änderungsarten (Aufschlag auf EK, Abschlag auf UVP, Festpreis, Abschlag auf VK, Abschlag auf Listenpreis). | `CustomerSpecialPrice`, `SpecialPriceKind` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:232-259` |
| **Vertragssonderpreis** | Vertragsbezogene Preiskondition, kombinierbar aus fünf Preisbasen und zwei Änderungsmodi (absolut/prozentual). Die Werte sind vorzeichenverkehrt hinterlegt. | `ContractSpecialPrice`, `ContractSpecialPriceKind`, `ContractSpecialPriceChangeKind` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-227` |
| **Staffelpreis** | Mengenabhängiger Preis, der nachrangig zu Sonderpreisen greift. | `ArticleVolumePrices`, `ArticleVolumePricesBL` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:261-266` |
| **Mehrwertsteuersatz** | Steuersatz mit Ablaufdatum und Verweis auf den Folgesatz; bildet eine zeitliche Kette. | Entität `ValueAddedTax` mit `NextTaxRate`, `ExpirationDate`; `TaxBL` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237` |
| **Provisionsschema** | Regelwerk zur Ermittlung von Vertriebsprovisionen, zuordenbar zu Kunden und Mitarbeitern, mit Zielvorgaben und Stufen. | `ReceiptProvisionSchema`, `…SchemaItem`, `…SchemaCustomerAssignment`, `…EmployeeGoal`, `…EmployeeLevel` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs` |
| **Mahnstufe** | Eskalationsstufe einer überfälligen Forderung; vier Ausprägungen (keine, 1, 2, 3). | `DunningLevel.None`, `Level1`, `Level2`, `Level3` | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-210` |
| **Mahnstopp** | Befristete Aussetzung des Mahnverfahrens, setzbar je Kunde oder je Beleg, mit Begründung. | `DunningStop`, `DunningStopBegin`, `DunningStopEnd`, `DunningInfo` | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431` |
## 5. Verträge und Service
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Vertrag** | Belegart für wiederkehrende Leistungen mit Abrechnungsintervall, Laufzeit und optionaler automatischer Verlängerung. | `ReceiptContract`, `ContractClass = 22`, Tabellen `VertragKopf`/`VertragPos` | `docs/reference/receipts/contracts-backend.md:11-95` |
| **Abrechnungsintervall** | Zyklus, in dem aus einem Vertrag Rechnungen erzeugt werden (Art × Dauer, z. B. Monat × 3 = quartalsweise). | `BillingIntervalKind`, `BillingIntervalDuration` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:836` |
| **Kalkulationsart (Vertrag)** | Steuert, ob ein Vertrag automatisch, nach Bedarf oder manuell abgerechnet wird. | `ContractCalculationKind.Auto`, `Need`; `ContractNeedCalcKind.Dynamic` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:829-830, 882-884` |
| **Vertragszusatzart** | Kennzeichnet, ob ein Vertrag einfach, klickbasiert (Geräte­zähler) oder kontingentbasiert ist. | `ContractExtraKind.Easy`, `ClickDevice`, `Contingent` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:837-840` |
| **Kontingent** | Vorab vereinbartes Leistungsvolumen (Stunden oder Betrag), das über die Vertragslaufzeit verbraucht wird. | `IReceiptWithContingent` mit `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentLimitValue` u. a. | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10318-10369` |
| **Stammblatt** | Liste von Geräten oder Objekten, die einem Vertrag zugeordnet sind (Grundlage für Klickabrechnung). | `MasterDataList`, `MasterDataListItem`, `MasterDataListClass = 25` | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:59, 314` |
| **Helpdesk-Ticket** | Serviceanfrage mit Nummer, Kunde, Status, Priorität, Typ, bis zu drei Kategorieebenen, Verantwortlichem und Fälligkeit. | Entität `Helpdesk` / `HelpdeskCompact`, Tabelle `hlpdsk_requests`, `HelpdeskClass = 10` | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:12-120` |
| **Ticketstatus** | Frei konfigurierbarer Bearbeitungsstand eines Helpdesk-Tickets. Ein Statuswert ist in den Einstellungen als „geschlossen" ausgezeichnet. | `HelpdeskStateI3D`, `HelpdeskSettingsBL.GetClosedHelpdeskState()` | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433` |
| **Zeiterfassung (Helpdeskzeit)** | Erfasste Arbeitszeit zu einem Ticket, unterschieden nach Berechenbarkeit, Planungsstatus und Abrechnungszustand. | `HelpdeskTimer`, `HelpdeskTimerBillingState`, `HelpdeskTimerTypes` | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90` |
| **RMA** | Rücksendungs- und Reparaturvorgang (Return Merchandise Authorization), kunden- und lieferantenseitig getrennt geführt. | `RmaBL`, `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180` |
## 6. Schnittstellen und Datenaustausch
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **EDI** | Elektronischer Geschäftsdatenaustausch mit Distributoren (Auftragsbestätigung, Lieferavis, Rechnung). | `SupplierEdiBL` mit lieferantenspezifischen Partial Classes, `EDILogBL` | `src/backend/Centron.BL/EDI/SupplierEDI/` |
| **EDI-Format** | Datenformat eines Distributors. Unterstützt werden OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron und ZUGFeRD. | `EdiDataType` | `docs/reference/edi/edi-architecture.md:177-188` |
| **ZUGFeRD / XRechnung** | Standards für strukturierte elektronische Rechnungen. ZUGFeRD bettet die XML-Rechnung in ein PDF/A-3 ein; XRechnung ist das rein strukturierte Format der öffentlichen Verwaltung. | `ZugferdKind` (6 Profilstufen), `InvoiceZugferdBL` | `src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:11-27` |
| **Guideline-ID** | Normkennung, die das verwendete E-Rechnungsprofil im XML ausweist (KoSIT-URN). | Zuordnung in `InvoiceZugferdBL` | `…/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289` |
| **Buchhaltungsexport** | Übergabe von Debitoren- und Kreditorenbuchungssätzen an die Finanzbuchhaltung, optional als DATEV-Online-Paket mit Belegbild. | `BookKeepingExportBL`, `GetDatevOnlinePackageForExport` | `…/DataExchange/BookKeeping/BookKeepingExportBL.cs:832, 1437, 1560` |
| **finAPI** | Bankenaggregator zur Abfrage von Kontoumsätzen; getrennte Sandbox- und Live-Endpunkte. | `Centron.APIs.FinAPI`, `FinApiClient` | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
## 7. Technische Querschnittsbegriffe
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **I3D** | Systemweite Bezeichnung für den technischen Primärschlüssel („ID 3develop"). Jede Tabelle besitzt eine Spalte `I3D` als `int IDENTITY(1,1)`. Fremdschlüsselspalten enden auf `I3D`. | Spalte `I3D`, Suffix `…I3D` | `docs/guides/database/database-conventions.md:12-36` |
| **Objektart (ObjectKind)** | Numerischer Diskriminator für polymorphe Referenzen nach dem Muster `ObjectI3D` + `ObjectKind`. In Altbeständen `AnlageI3D` + `AnlageArt`. | `CentronObjectKindNumeric` (über 230 Werte) | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:20-264` |
| **Ergebnisobjekt (`Result<T>`)** | Einheitlicher Rückgabetyp der Geschäftslogik mit Zustand, Meldung und maschinenlesbarem Fehlercode. | `Result`, `Result<T>`, `ResultStatus`, `DefaultMessageCodes` | `src/backend/Centron.Interfaces/BL/` |
| **BL-Logik / WS-Logik** | Doppelimplementierung einer Clientfunktion: `BL*Logic` greift direkt auf die Datenbank zu, `WS*Logic` ruft den Anwendungsserver. | `I{Modul}Logic`, `BL{Modul}Logic`, `WS{Modul}Logic`, `ClassContainer` | `docs/getting-started/general-structure.md:36-113` |
| **WebServiceBL** | Schicht, die Domänenentitäten in DTOs umwandelt und die Dienstfassade bedient. | `*WebServiceBL`-Klassen unter `Centron.BL/WebServices` | `src/backend/Centron.BL/WebServices/` (464 Dateien) |
| **SpecificLogic** | Belegartspezifische Implementierung, an die die generische Belegverarbeitung delegiert. | `OfferSpecificLogic`, `InvoiceSpecificLogic`, `ContractSpecificLogic` u. a.; Verteiler `SpecificLogics` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7267, 10277` |
| **Legacy-Sicht** | Englisch benannte Datenbanksicht auf eine deutsch benannte Alttabelle; normalisiert Spaltennamen, Nullwerte und ungültige Datumswerte. | `Offers`, `Orders`, `DeliveryLists`, `Invoices`, `Contracts`, `CreditVouchers`, `PickupLists` | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs` |
| **Versionstabelle** | Strukturgleiche Kopie einer Belegtabelle zur Archivierung früherer Belegversionen. | `*KopfVersions`, `*PosVersions` mit `OriginalI3D` / `KopfVersionsI3D` | `docs/reference/receipts/receipts-backend-architecture.md:147-172` |
| **Migrationsskript** | Nummerierte, versionsgebundene und genau einmal ausführbare Schemaänderung. | `ScriptMethod<Nummer> : BaseScriptMethod`, Ausführungsstand in Tabelle `DBUpdate` | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177` |
| **Anwendungseinstellung** | Betreiberseitig konfigurierbarer Parameter. Es existieren zwei Systeme: Alttabelle `Stammdat` und aktuelle Tabelle `ApplicationSettings`. | `AppSettingsConst`, `ApplicationSettingID`, `AppSettingsBL`, `AppSettingsGroupBL` | `docs/guides/development/settings-management.md:5-31` |
| **Hintergrunddienst** | Zeitgesteuerter, unbeaufsichtigt laufender Verarbeitungsprozess im Anwendungsserver. | Ableitungen von `ManagedBackgroundService` (33 Dienste) | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:12-180` |
| **Interceptor** | Querschnittliche Vor- und Nachverarbeitung von Dienstaufrufen (Authentifizierung, Protokollierung, Fehlerbehandlung, Telemetrie) mit definierter Reihenfolge. | Castle-DynamicProxy-Interceptoren mit `Priority`, gesteuert über Attribute | `…/WcfBridge/Interception/Interceptors/` |
| **Nexus** | Blazor-basierte Webanwendung der Suite („c-entron Web"), enthält Service-Board, WebCart, WebOffer und Verwaltungsfunktionen. | Projekte `CentronNexus`, `CentronNexus.Host` | `README.md:1`, `docker/compose/compose.yaml:38-50` |
| **Service-Board** | Ticket- und Servicearbeitsplatz innerhalb von Nexus, auch als eigenständig lizenziertes Produkt geführt. | `CentronNexus/ServiceBoard/`, `ApplicationKind.ServiceBoard`, `ServiceBoardNext` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45, 53` |
| **WebCart** | Kundenshop innerhalb von Nexus; die verfügbaren Artikel stammen aus den Sonderpreisen des jeweiligen Kunden. | `CentronNexus/WebCart/`, `ApplicationKind.WebCart` | `README.md:31-36` |
| **Riversuite / DocuBoard** | Angrenzende Produktfamilie (Inventarisierung, Monitoring, Fernwartung), die sich am selben Anwendungsserver anmeldet. | `ApplicationKind.Riversuite*`, `LicenseGuids.Riversuite*` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:34-44` |
| **c-entron Delphi** | Vorgängersystem, das dieselbe Datenbank und dieselben Lizenz-GUIDs nutzt. Seine Versionsnummern (9.3.x) werden bei der Lizenzprüfung gesondert behandelt. | `LicenseManager.TryFixCentronDelphiVersionNumber` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:304-330` |
@@ -0,0 +1,311 @@
# Hypothesen und offene Fragen
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Zweck:** Sammlung aller Aussagen, die aus den vorliegenden Artefakten **nicht** eindeutig
abgeleitet werden konnten, samt der jeweils fehlenden Information. Jede Hypothese ist an eine
konkrete offene Frage für die manuelle Validierung durch Fachexperten (Schritt 7 der
RRE-Methodenkette) gebunden.
**Lesart:** `Betroffene Anforderung` verweist auf die Stelle, an der die Teilaussage mit
`[HYPOTHESE]` markiert ist. `Beobachtung` nennt, was tatsächlich im Artefakt steht.
`Fehlende Information` benennt, was zur Bestätigung oder Widerlegung erhoben werden müsste.
---
## HYP-001 — Nicht analysierte Module
**Betroffene Anforderung:** keine einzelne; betrifft die Vollständigkeit der Spezifikation insgesamt.
**Beobachtung:** Die Codebasis umfasst 14 782 C#-, 1 233 XAML- und 491 Razor-Dateien in 44 Projekten.
In diesem Lauf wurden schwerpunktmäßig Beleg-, Rechte-, Lizenz-, Anmeldungs-, Vertrags-, Helpdesk-,
Lager-, Steuer-, EDI-, E-Rechnungs-, DSGVO-, Betriebs- und Migrationslogik analysiert. Ganze
Modulbereiche wurden nicht geöffnet, darunter: `Statistics` (141 UI-Dateien, `ContractEvaluationBL`
87 KB, `MspCollectorsBL` 70 KB), `Survey` (64 UI-Dateien), `Massenupdates` (48), `Production`,
`ProjectPriceImport`, `PLM`, `QM`, `TelekomDive`, `PayersAndCostCenter`, `ArtificialIntelligence`
(68 UI-Dateien, `Centron.BL/ArtificialIntelligence` 25 Dateien), `Centron.Controls/PasswordManager`
(69 Dateien), `Centron.Controls/MyDay` (58), `Centron.Controls/Telephony`/`Tapi`,
`CentronNexus.OutlookAddIn`, `Centron.Api.docuFORM`, `Centron.Api.Gls`, `Centron.Api.Shipcloud`,
`Centron.APIs.CopDataAccess`, `Centron.APIs.IcecatDataAccess`, `Centron.APIs.ITscopeDataAccess`.
**Aussage [HYPOTHESE]:** Die in dieser Spezifikation dokumentierten Architektur- und
Querschnittsmuster (Schichtung, `Result<T>`, Rechteprüfung über `UserRightsConst`, Nummernkreise,
Sitzungscache, `ManagedBackgroundService`) gelten auch für die nicht analysierten Module.
**Fehlende Information:** Stichprobenanalyse mindestens eines Moduls je nicht abgedecktem Bereich.
**Empfehlung:** Nachschlag in einer Folge-Iteration mit Schwerpunkt Statistik/Auswertung,
Passwortmanager, Telefonie/TAPI und den Fremd-API-Anbindungen.
---
## HYP-002 — Erzwingung der Transportverschlüsselung
**Betroffene Anforderung:** SyRS-033 (Transportverschlüsselung und Zertifikatskonfiguration)
**Beobachtung:** `WebServiceConfig` enthält die Felder `WebServiceCertificateFilePath` und
`WebServiceCertificatePassword`; `appsettings.Production.json` des Nexus enthält
`Host.LinuxCertificatePath` und `Host.LinuxCertificatePassword`. Sämtliche mitgelieferten
Beispielkonfigurationen verwenden `http://` und leere Zertifikatsfelder.
**Aussage [HYPOTHESE]:** Bei hinterlegtem Zertifikat werden unverschlüsselte Aufrufe abgewiesen
oder auf HTTPS umgeleitet.
**Fehlende Information:** Der Kestrel-/Host-Konfigurationscode, der die Endpunkte aus diesen
Feldern aufbaut, wurde nicht gelesen. Es ist unbekannt, ob ein HTTP-Endpunkt parallel bestehen
bleibt, ob HSTS oder eine Umleitung aktiv ist und ob TLS-Mindestversionen gesetzt werden.
**Offene Frage an den Fachexperten:** Wird in Produktivinstallationen HTTPS erzwungen, oder ist
der Betrieb über HTTP in Kundennetzen üblich? Existiert ein vorgelagerter Reverse Proxy, der die
Terminierung übernimmt (die Auswertung von `X-Forwarded-For` in `TicketAuthenticationHandler`
legt dies nahe)?
---
## HYP-003 — Terminierung der Nummernreservierungsschleife
**Betroffene Anforderung:** SwRS-011 (Kollisionsfreie Nummernreservierung ohne Sperrung)
**Beobachtung:** `NumberGroupBL.GetNextNumber` enthält ein `while (true)` ohne Abbruchbedingung,
ohne Versuchszähler und ohne Wartezeit zwischen den Versuchen. Verlassen wird die Schleife nur,
wenn das bedingte `UPDATE` genau eine Zeile ändert.
**Aussage [HYPOTHESE]:** Die Schleife terminiert auch unter hoher Nebenläufigkeit in endlicher Zeit.
**Fehlende Information:** Es liegt kein Lasttest und keine Betriebsstatistik vor. Ebenfalls
unbekannt ist, ob die zusätzlich in `FindNextNumber` enthaltene innere `while`-Schleife (die
so lange zählt, bis eine in der Zieltabelle unbenutzte Nummer gefunden ist) bei großen Lücken
zu Laufzeitproblemen führt – sie führt je Schritt eine eigene `SELECT COUNT(*)`-Abfrage aus.
**Offene Frage an den Fachexperten:** Sind in der Praxis Hänger oder auffällige Wartezeiten bei
der Belegnummernvergabe bekannt, insbesondere bei Mandanten mit großen Nummernbereichen oder
vielen gleichzeitigen Anwendern?
---
## HYP-004 — Schutz bereits fakturierter Servicezeiten
**Betroffene Anforderung:** StRS-009 (Leistungszeiterfassung und Fakturierung von Servicezeiten)
**Beobachtung:** `CentronRights.md` (KONTEXT) beschreibt zu den Rechten „Helpdeskzeiten
verschieben" und „Helpdeskzeiten löschen" jeweils den Zusatz „But only if the ticket is not part
of a receipt." Im gelesenen Code (`HelpdeskTimerBL.cs:556`) wurde nur die Rechteprüfung
`DELETE_HELPDESK_TIMER` bestätigt, nicht jedoch die Prüfung auf Belegzugehörigkeit.
**Aussage [HYPOTHESE]:** Das Verschieben und Löschen einer Zeiterfassung ist technisch gesperrt,
sobald die Zeit Teil eines Belegs ist.
**Fehlende Information:** Vollständige Lektüre von `HelpdeskTimerBL` (36 KB),
`ReceiptItemTimerBL` (104 KB) und `TimerBillingBL` (32 KB) hinsichtlich einer Prüfung auf
`HelpdeskTimerBillingState` bzw. eine Belegreferenz.
**Offene Frage an den Fachexperten:** Ist diese Sperre fachlich zwingend (Konsistenz der
Fakturierung) und wird sie im Betrieb tatsächlich beobachtet? Für die Zielarchitektur ist dies
eine abrechnungsrelevante Integritätsregel.
---
## HYP-005 — Sicherheitsauswirkung der Ticketübergabe im Query-String
**Betroffene Anforderung:** SwRS-026 (Ticketprüfung als ASP.NET-Core-Authentifizierungsschema)
**Beobachtung:** `TicketAuthenticationHandler.GetTicket()` prüft **zuerst** den Query-Parameter
`access_token` und erst danach den `Authorization`-Header.
**Aussage [HYPOTHESE]:** Die Übergabe im Query-String führt dazu, dass gültige Sitzungstickets
in Zugriffsprotokollen von Webservern, Reverse Proxies oder Browserhistorien erscheinen.
**Fehlende Information:** Es ist nicht belegt, welche Clients diesen Weg tatsächlich nutzen
(vermutlich SignalR-Verbindungen, da diese keine Header setzen können) und ob die Protokollierung
der Query-Zeichenkette in den Betriebsumgebungen aktiv ist.
**Offene Frage an den Fachexperten:** Wird der Query-String-Weg produktiv benötigt? Falls ja,
sollte im Zielsystem ein kurzlebiges, auf den Verbindungsaufbau beschränktes Token verwendet
werden.
---
## HYP-006 — Vollständigkeit der Doppelimplementierung BL/WS
**Betroffene Anforderung:** SyRS-041 (Umschaltbare Datenzugriffsart des Fachclients)
**Beobachtung:** `docs/getting-started/general-structure.md` verlangt ausdrücklich, dass jedes
Modul beide Datenzugriffswege implementiert. Im Verzeichnis `src/centron/Centron.WPF.UI/Services`
liegen 688 Dateien. Es wurde nicht geprüft, ob zu jeder `I*Logic`-Schnittstelle tatsächlich
sowohl eine `BL*`- als auch eine `WS*`-Implementierung existiert.
**Aussage [HYPOTHESE]:** Alle Clientmodule sind sowohl mit direktem Datenbankzugriff als auch
über den Web-Service lauffähig.
**Fehlende Information:** Automatisierter Abgleich der Schnittstellen- und Implementierungsnamen
über alle Module hinweg; zusätzlich die Auswertung der `SupportsConnectionTypes`-Deklarationen
aller `AppModuleController`.
**Offene Frage an den Fachexperten:** Welche Betriebsart ist in der Kundenbasis vorherrschend?
Falls der direkte Datenbankzugriff nur noch selten genutzt wird, entfällt für die
Web-/SaaS-Neuimplementierung ein erheblicher Teil des Migrationsumfangs (siehe K-03 in
`Traceability.md`).
---
## HYP-007 — Inhalt und Steuerbarkeit der Telemetrie
**Betroffene Anforderung:** SyRS-043 (Erhebung und Übermittlung von Betriebstelemetrie)
**Beobachtung:** Es existieren `TelemetryAggregator`, `HttpTelemetryUploadClient`,
`DatabaseGuidProvider`, `HardwareIdProvider`, `ApiCallTelemetryInterceptor`,
`McpToolUsageTelemetryInterceptor`, `CentronAnalytics` sowie die Dienste `TelemetryFlushService`
(1 min) und `TelemetryUploadService` (15 min). Die konkreten Nutzdaten wurden nicht gelesen.
**Aussage [HYPOTHESE]:** Die Telemetrie enthält keine personenbezogenen Daten und kann vom
Betreiber deaktiviert werden.
**Fehlende Information:** Inhalt der übertragenen Datenstruktur, Zieladresse, Rechtsgrundlage
und das Vorhandensein eines Abschaltschalters. Da beide Dienste von `ManagedBackgroundService`
erben, sind sie technisch über `BackgroundServiceBL` abschaltbar – ob dies dem Betreiber im
UI angeboten wird, ist nicht belegt.
**Offene Frage an den Datenschutzbeauftragten und Fachexperten:** Welche Felder werden
übertragen? Existiert eine Auftragsverarbeitungsvereinbarung oder ein Einwilligungsmechanismus?
Für ein SaaS-Zielsystem ist diese Frage neu zu bewerten.
---
## HYP-008 — Vollständiger Aufgabenkatalog des DataQualityService
**Betroffene Anforderung:** SwRS-035 (Aufgabenkatalog der Datenqualitätspflege)
**Beobachtung:** Im Quelltext wurden die ersten drei Aufgaben verifiziert
(`TicketPatternUpdateCustomerMappings`, `ExecuteDirectoryCheck`, `CleanupCentronNotifications`).
Die Aufgaben 4–9 (Checklisten-Kundenzuordnungen, Reorganisation der Profilereinträge,
`ToDoBL.DataQualityFillAccountI3D`, `AccountBL.CheckAndRepairAccountTypeToAccountsTable`,
`HelpdeskTimerBL.DataQualityUpdateMissingHelpdeskTimerProperties`,
`SecondStockArticleBL.DataQualityCleanupSecondaryStockArticles`) stammen ausschließlich aus
`docs/Background Service/DataQualityService.md`.
**Aussage [HYPOTHESE]:** Der Dienst führt genau die neun in der Dokumentation genannten Aufgaben
in der dort angegebenen Reihenfolge aus.
**Fehlende Information:** Lektüre von `DataQualityService.cs` ab Zeile 71 bis zum Ende.
**Bewertung:** Geringes Risiko; die Aussage ist mit vertretbarem Aufwand im Code verifizierbar
und wurde hier nur aus Aufwandsgründen nicht abgeschlossen.
---
## HYP-009 — Belegzustandsmodell in der Entwicklerdokumentation
**Betroffene Anforderung:** SyRS-014 (Belegzustandsmodell mit drei Zuständen)
**Beobachtung:** `docs/reference/receipts/receipts-backend-architecture.md:284-290` beschreibt
vier Belegzustände „Draft – Released – Processed – Cancelled". Der Code definiert in
`ReceiptState` jedoch nur drei Zustände: `Active (offen)`, `Completed (abgeschlossen)`,
`Canceled (storniert)`. Es gibt im Code keinen Hinweis auf „Draft" oder „Released".
**Aussage [HYPOTHESE]:** Die Dokumentation beschreibt einen geplanten oder aus einem anderen
System übernommenen Zustandsraum, der nie implementiert wurde.
**Fehlende Information:** Herkunft der Dokumentationsaussage. Zusätzlich ist unklar, ob der
Belegsperrmechanismus (`TryLockReceipt`) oder das Feld `ReceiptUserStateI3D` (in den Belegsichten
enthalten, siehe `ScriptMethod11803`) einen zweiten, benutzerdefinierten Zustandsraum bildet.
**Offene Frage an den Fachexperten:** Existiert neben `ReceiptState` ein fachlich relevanter,
frei konfigurierbarer Belegstatus (`ReceiptUserState`)? Falls ja, ist er in einer Folge-Iteration
als eigene Anforderung zu erfassen.
**Bewertung:** Dieser Widerspruch ist der Beleg dafür, dass die Entwicklerdokumentation unter
`docs/` in dieser Spezifikation zu Recht durchgängig als `KONTEXT` und nicht als `PRIMÄR`
klassifiziert wurde.
---
## HYP-010 — Wirksamkeit der Rechteänderung innerhalb einer laufenden Sitzung
**Betroffene Anforderung:** SyRS-011 (Auflösung von Benutzerrechten über Gruppenzugehörigkeit),
SwRS-016 (Sitzungsbezogene Zwischenspeicherung von Rechten)
**Beobachtung:** `AppRightsBL.HasUserRight` liest die Rechtemenge über
`Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", …)`. Es wurde keine
Invalidierung dieses Cache-Eintrags bei Rechteänderungen gefunden. Gleichzeitig existiert mit
`CheckRightsFromUser` ein zweiter, nicht gecachter Prüfpfad.
**Aussage [HYPOTHESE]:** Ein Rechteentzug wirkt für einen bereits angemeldeten Benutzer erst
nach Ablauf der Sitzung bzw. nach Neuanmeldung.
**Fehlende Information:** Lebensdauer einer `BLSession` im Web-Service-Betrieb (pro Aufruf oder
pro Sitzung) und das Vorhandensein einer Cache-Invalidierung an anderer Stelle.
**Offene Frage an den Fachexperten:** Ist ein sofort wirksamer Rechteentzug fachlich gefordert
(z. B. bei Freistellung eines Mitarbeiters)? Für ein SaaS-Zielsystem ist dies eine
sicherheitsrelevante Entwurfsentscheidung.
---
## HYP-011 — Reichweite der optimistischen Nebenläufigkeitsprüfung
**Betroffene Anforderung:** SyRS-017 (Schutz vor konkurrierenden Belegänderungen)
**Beobachtung:** Die Prüfung `if (concurrencyControlGuid != null && receipt.ConcurrencyControlGuid
!= concurrencyControlGuid)` wurde an sieben Stellen in `ReceiptBL` gefunden – ausschließlich in
Einzelfeld-Änderungsmethoden (Zahlung, Einkaufspreis, kommissionierte Menge u. a.). Im
allgemeinen Speicherpfad `SaveReceipt<T, TReceiptItem>` wurde keine entsprechende Prüfung
gefunden; dort greift stattdessen die Versionsnummernvalidierung und die pessimistische Sperre.
**Aussage [HYPOTHESE]:** Der allgemeine Speicherpfad ist durch die Kombination aus
Versionsnummernvalidierung und pessimistischer Belegsperre gegen Datenverlust bei
konkurrierender Bearbeitung ausreichend geschützt.
**Fehlende Information:** Verhalten bei Umgehung der Sperre (z. B. abgestürzter Client, dessen
Sperre über `UnLockReceipt(..., onlyIfLockedByCurrentUser: false)` aufgehoben wird) sowie das
Verhalten bei gleicher Versionsnummer (Fall `isCurrentVersion`, in dem eine Änderung ohne
Versionsanhebung gespeichert wird).
**Offene Frage an den Fachexperten:** Sind Fälle bekannt, in denen Belegänderungen ohne
Fehlermeldung verloren gingen? Diese Frage betrifft unmittelbar die Zuverlässigkeit des
Zielsystems.
---
## HYP-012 — Belastbarkeit der aus `docs/` übernommenen Strukturaussagen
**Betroffene Anforderungen:** StRS-015, SwRS-006, SwRS-007, SwRS-008, SwRS-046, SyRS-024
**Beobachtung:** Mehrere Struktur- und Tabellenaussagen stützen sich in Teilen auf die
Entwicklerdokumentation, insbesondere: die vollständige Liste der Tabellen-/Sicht-/Versionspaare
über alle sieben Belegarten, die `AnlageArt`-Codes der gemeinsamen Logtabelle (1 = Angebot,
2 = Auftrag, 3 = Lieferschein, 4 = Rechnung, 5 = Abholschein, 6 = Gutschrift, 22 = Vertrag),
die Liste der `SaveReceipt*Repository`-Klassen sowie die EDI-Formatliste und die
`EDILogState`-Werte. Im Code stichprobenartig verifiziert wurden davon: das Lieferschein-Paar
(`LiefKopf`/`LiefKopfVersions` → `DeliveryLists`/`DeliveryListVersions`, über
`ScriptMethod11803`), die Belegartcodes über `CentronObjectKindNumeric` und die Existenz der
lieferantenspezifischen EDI-Partial-Dateien.
**Aussage [HYPOTHESE]:** Die nicht einzeln verifizierten Struktur- und Codeaussagen der
Entwicklerdokumentation treffen zu.
**Fehlende Information:** Ein maschineller Abgleich des tatsächlichen Datenbankschemas (Tabellen,
Sichten, Spalten) gegen die Dokumentation. Ein Datenbankschema-Abzug lag im Arbeitsverzeichnis
nicht vor; die Struktur ist nur indirekt über die 764 Migrationsskripte rekonstruierbar.
**Offene Frage an den Fachexperten:** Kann für die Folge-Iteration ein Schemaabzug
(Tabellen-, Spalten- und Constraint-Liste) bereitgestellt werden? Das würde die überwiegende
Mehrheit der `KONTEXT`-Belege im Datenmodellbereich durch `PRIMÄR`-Belege ersetzen und ist die
wirkungsvollste Einzelmaßnahme zur Erhöhung der Belegqualität.
---
## Übersicht
| ID | Kurzbezeichnung | Betroffene Anforderung(en) | Risiko für die Migration |
|---|---|---|---|
| HYP-001 | Nicht analysierte Module | Vollständigkeit gesamt | hoch (Umfangsschätzung) |
| HYP-002 | Erzwingung von TLS | SyRS-033 | mittel (Sicherheit) |
| HYP-003 | Terminierung der Nummernschleife | SwRS-011 | mittel (Zuverlässigkeit) |
| HYP-004 | Schutz fakturierter Zeiten | StRS-009 | hoch (Abrechnungsintegrität) |
| HYP-005 | Ticket im Query-String | SwRS-026 | mittel (Sicherheit) |
| HYP-006 | Vollständigkeit BL/WS-Doppelpfad | SyRS-041 | hoch (Migrationsumfang) |
| HYP-007 | Telemetrieinhalt und Opt-out | SyRS-043 | mittel (Datenschutz) |
| HYP-008 | Aufgaben 4–9 der Datenqualität | SwRS-035 | gering |
| HYP-009 | Widerspruch Belegzustandsmodell | SyRS-014 | mittel (Fachmodell) |
| HYP-010 | Sofortwirksamkeit von Rechteentzug | SyRS-011, SwRS-016 | hoch (Sicherheit) |
| HYP-011 | Reichweite des Nebenläufigkeitsschutzes | SyRS-017 | hoch (Datenverlust) |
| HYP-012 | Nur dokumentierte Schemaaussagen | StRS-015, SwRS-006/-007/-008/-046, SyRS-024 | hoch (Datenmodell) |
@@ -0,0 +1,568 @@
# StRS – Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Ebene:** Stakeholder Requirements (ISO/IEC/IEEE 29148:2018, Kap. 9.2)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Erstellt:** 2026-08-25 · Reverse Requirements Engineering, rein statische Analyse
**Sprache:** Anforderungsaussagen deutsch; technische Bezeichner in Originalsprache
---
## 0. Vorbemerkung zur Lesart
Jede Anforderung trennt strikt zwischen `Fakt` (was im Artefakt nachweisbar steht) und `Aussage`
(fachliche Interpretation). Belege sind klassifiziert als `PRIMÄR` (durchgesetzte Regel in Code
oder DB-Constraint), `SEKUNDÄR` (UI-Text, Fehlermeldung, Mapping, Konfigurationsschalter) und
`KONTEXT` (Kommentar, Commit, Ticketreferenz, Entwicklerdokumentation).
Die Entwicklerdokumentation unter `docs/` ist durchgängig als `KONTEXT` klassifiziert, weil sie
nicht ausführbar ist und mindestens an einer Stelle nachweislich vom Code abweicht (siehe
`Analysebericht.md`, Abschnitt „Widersprüche").
Alle Pfadangaben sind relativ zum Wurzelverzeichnis der Codebasis.
---
## 1. Akteure und Stakeholder
Die folgenden Akteure sind aus den Authentifizierungs- und Rechtestrukturen ableitbar und werden
in den Anforderungen konsistent verwendet:
| Akteur | Technische Entsprechung | Beleg |
|---|---|---|
| **Interner Benutzer (Mitarbeiter)** | `AppUser` (Tabelle `Sichbenu`), verknüpft mit `EmployeeCompact` | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:157-218` |
| **Web-Account (Kunde des Kunden)** | `WebAccount`, eigene Rechtetabelle `WebAccountsRights` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:679-691` |
| **Administrator** | Mitglied der Gruppe „Administratoren" (`AppGroup.I3D == 6`) | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:359-360` |
| **Systemintegrator / Fremdanwendung** | `ApplicationKind` mit eigener Lizenz-GUID, Login am Web-Service | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| **API-Client (technisch)** | `AccessToken` (persönlicher Token, SHA-256-Hash) | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:377-400` |
| **Hintergrunddienst** | `ManagedBackgroundService`-Ableitungen im Web-Service | `src/webservice/Centron.Host/AspNetCore/HostedServices/` |
| **Lizenzgeber (NEXOWARE)** | Lizenzserver / `c-entron Office`, `LicenseManager` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs` |
| **Distributor / Lieferant (EDI-Partner)** | `SupplierEdiConfigurations`, `SupplierEdiBL.*` | `src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs` |
| **Finanzbuchhaltung / Steuerberater** | `BookKeepingExportBL`, DATEV-Online-Paket | `src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs:1560` |
| **Bank / Zahlungsdienstleister** | finAPI-Anbindung | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
---
## 2. Anforderungen
```
ID: StRS-001
Titel: Mandanten- und filialfähiger Geschäftsbetrieb
Ebene: StRS
Typ: funktional
Akteur: Administrator, Interner Benutzer
Vorbedingung: Ein Mandant (Mandator) ist als Default gekennzeichnet; optional sind Filialen (Branch) angelegt.
Fakt: `MandatorBL.GetDefaultMandator()` selektiert genau den Mandator mit `Default == 1`. `NumberGroupBL.RefreshAllNumberGroups()` legt für den Default-Mandanten und zusätzlich für jede Filiale (ohne Hauptsitz) eigene Nummernkreise an. `ReceiptBase` führt die Felder `BranchI3D` und `BranchOrigin`; `CentronObjectKindNumeric` kennt die Objektarten `Company = 53 // Mandant` und `Branch = 124`.
Aussage: Das System soll den Geschäftsbetrieb eines Mandanten mit optional mehreren Filialen abbilden, wobei Filialen eigene Nummernkreise erhalten und jeder Beleg einer Filiale zugeordnet werden kann.
Ergebnis: Belege, Nummernkreise und Sichtbarkeitsregeln sind eindeutig einem Mandanten und optional einer Filiale zugeordnet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/MandatorBL.cs:19-22 (`GetDefaultMandator`) – Begründung: Der Code setzt die Existenz genau eines Default-Mandanten als Systeminvariante voraus.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152 (`RefreshAllNumberGroups`) – Begründung: Erzeugt Nummernkreise je Filiale und belegt damit die Filialfähigkeit der Belegnummerierung.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:19-20 (`BranchI3D`, `BranchOrigin`) – Begründung: Jeder Beleg trägt eine Filialzuordnung im Datenmodell.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:31-32 (`Company = 53 // Mandant`, `Branch = 124`) – Begründung: Mandant und Filiale sind eigenständige, systemweit adressierbare Objektarten.
Prüfidee: Zwei Filialen anlegen, in jeder Filiale je eine Rechnung erzeugen und prüfen, dass die Nummernvergabe aus getrennten `NumberGroup`-Datensätzen erfolgt (unterschiedliche `Current`-Werte).
Tracelinks: SyRS-015, SyRS-012
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Rollenbasierte Zugriffssteuerung für interne Benutzer
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Benutzer ist am System angemeldet und Mitglied mindestens einer Rechtegruppe.
Fakt: Rechte werden nicht direkt an Benutzer, sondern über Gruppen vergeben: `AppRightsBL.GetAllAppRightsFromUser` liest per SQL `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `UserRightsConst` definiert über 1 000 Rechtekonstanten in einer hierarchischen Klassenstruktur (u. a. `Sales.Customer.Helpdesk`, `Administration.UserRightsManagement`, `Controlling.Finances`).
Aussage: Das System soll Zugriffsrechte ausschließlich über Rechtegruppen an interne Benutzer vergeben und für jede fachliche Funktion ein eigenes, feingranulares Recht führen.
Ergebnis: Ein Benutzer besitzt genau die Vereinigungsmenge der Rechte aller Gruppen, denen er angehört; ohne Gruppenzugehörigkeit besitzt er keine Rechte.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:651-664 (`GetAllAppRightsFromUser`) – Begründung: Zeigt die durchgesetzte Auflösung Benutzer→Gruppe→Recht auf Datenbankebene.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:63-87 (`GetRightsFromCurrentUser`) – Begründung: Bildet dieselbe Regel objektorientiert über `AppUser.Groups` ab.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (gesamte Datei, u. a. Zeilen 2189-2389) – Begründung: Katalog der fachlich unterscheidbaren Rechte je Belegart und Modul.
- [KONTEXT] docs/guides/development/check-userrights.md – Begründung: Entwicklerdokumentation beschreibt die drei Prüfstellen (ViewModel, ModuleRegistration, BL) und bestätigt die Absicht.
Prüfidee: Benutzer aus allen Gruppen entfernen; anschließend muss `AppRightsBL.HasUserRight(userI3D, beliebigesRecht)` durchgängig `false` liefern und jeder rechtebewehrte Aufruf mit `DefaultMessageCodes.RightCheckFailed` scheitern.
Tracelinks: SyRS-011, SyRS-012, SwRS-016, SwRS-017, SwRS-018
Konsolidierung: Kandidat: StRS-003 (Web-Account-Rechte bilden ein zweites, strukturell paralleles Rechtesystem)
Status: belegt
```
```
ID: StRS-003
Titel: Kundenselbstbedienung über getrenntes Web-Account-Rechtesystem
Ebene: StRS
Typ: funktional
Akteur: Web-Account (Kunde des Kunden)
Vorbedingung: Für einen Kunden ist im Adressstamm ein Web-Account angelegt.
Fakt: Es existiert ein vom Mitarbeiter-Rechtesystem vollständig getrennter Rechtekatalog `WebAccountRightsConst` (u. a. `WEBRIGHT_CREATEREQUEST = 26000`, `WEBRIGHT_SHOWALLINVOICES = 61001`, `WEBRIGHT_SHOWONLYOWNINVOICES = 61002`). Die Auflösung erfolgt über `SELECT WebRightsI3D FROM WebAccountsRights WHERE WebAccountsI3D = :WebAccountI3D`. `ReceiptBL.CanUserViewReceipt` verweigert Web-Account-Logins den Belegzugriff generell.
Aussage: Das System soll Endkunden über ein eigenständiges Web-Account-Konto Selbstbedienungsfunktionen (Ticketerfassung, Belegeinsicht, Shop) anbieten, deren Berechtigungen unabhängig vom Mitarbeiter-Rechtesystem verwaltet werden.
Ergebnis: Ein Web-Account sieht ausschließlich die ihm über `WebAccountsRights` freigeschalteten Daten und hat keinen Zugriff auf die interne Belegbearbeitung.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/WebAccountRightsConst.cs:9-79 – Begründung: Eigener, disjunkter Rechte-Nummernraum für Web-Accounts.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:666-691 (`HasWebAccountRight`, `GetAllWebRightsFromWebAccount`) – Begründung: Getrennter Auswertungspfad gegen `WebAccountsRights`.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (`CanUserViewReceipt`: „Web-Benutzer haben keine Berechtigung Belege einzusehen.") – Begründung: Explizite, durchgesetzte Abgrenzung der beiden Akteursklassen.
- [SEKUNDÄR] README.md:31-36 (Abschnitt „WebCart") – Begründung: Beschreibt den WebCart als Funktion „primarily intended for the customers of our customers" und den Login als Web-Account.
Prüfidee: Mit einem Web-Account anmelden und `GetReceiptByI3D` aufrufen; der Aufruf muss mit `RightCheckFailed` und der Meldung „Web-Benutzer haben keine Berechtigung Belege einzusehen." abgewiesen werden.
Tracelinks: SyRS-013, SwRS-041
Konsolidierung: Kandidat: StRS-002 (zwei parallele Rechtemodelle mit gleicher fachlicher Absicht; Zusammenführung im Zielsystem prüfen)
Status: belegt
```
```
ID: StRS-004
Titel: Lizenzabhängiger Funktionsumfang
Ebene: StRS
Typ: nicht-funktional (Geschäftsmodell)
Akteur: Lizenzgeber (NEXOWARE), Administrator
Vorbedingung: Der Web-Service kann eine Lizenzdatei vom Lizenzserver beziehen oder besitzt eine gültige zwischengespeicherte Lizenz.
Fakt: `LicenseManager.HasLicense(Guid)` und `GetLicenseCount(Guid)` steuern die Verfügbarkeit einzelner Funktionen. `ApplicationKind` bindet jede anmeldefähige Anwendung an eine Lizenz-GUID; `CheckLicense` prüft zusätzlich Versionsgültigkeit und Anzahl gleichzeitig genutzter Lizenzen. `AccessTokenBL.ValidateToken` verweigert die Tokenprüfung ohne `LicenseGuids.AccessTokenModule`; `AuthenticatorFactory` verweigert OpenID-Connect ohne `LicenseGuids.OpenIDConnectAuthentication`.
Aussage: Das System soll den nutzbaren Funktionsumfang und die Anzahl gleichzeitiger Anmeldungen anhand einer serverseitig geprüften Lizenz steuern.
Ergebnis: Nicht lizenzierte Module bleiben verborgen oder liefern eine Lizenzfehlermeldung; bei Erreichen der Lizenzanzahl wird die Anmeldung mit `DefaultMessageCodes.LicenseMaximumReached` abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302 (`CheckLicense`) – Begründung: Prüft Lizenzbesitz, Versionsgültigkeit und Ticketanzahl gegen `GetLicenseCount`.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:382-383 – Begründung: Harte Lizenzsperre für das Access-Token-Modul.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:132-133 – Begründung: Harte Lizenzsperre für OpenID Connect.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53 – Begründung: Vollständige Registrierung aller anmeldefähigen Produkte mit Lizenz-GUID, `ExpirationKind` und `LicenseUsageKind`.
- [KONTEXT] docs/reference/security/licensing-system.md – Begründung: Erläutert Lizenzmodell (GUID, count, valid until date/version) und bestätigt die Interpretation.
Prüfidee: Lizenzdatei ohne `LicenseGuids.PasswordManager` einspielen; das Passwortmanager-Modul darf im Client nicht registriert werden und der zugehörige Web-Service-Aufruf muss eine Lizenzfehlermeldung liefern.
Tracelinks: SyRS-007, SwRS-020, SwRS-021, SwRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Durchgängiger Verkaufsbelegfluss
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertrieb, Innendienst)
Vorbedingung: Ein Kunde (Account/Kunde) ist im Stammdatenbestand angelegt.
Fakt: Es existieren sieben Kundenbelegarten mit einheitlicher Basisklasse `ReceiptBase`: Angebot (`OfferClass = 1`), Auftrag (`OrderClass = 2`), Lieferschein (`DeliveryListClass = 3`), Rechnung (`InvoiceClass = 4`), Abholschein (`PickupListClass = 5`), Gutschrift (`CreditVoucherClass = 6`), Vertrag (`ContractClass = 22`). `CentronObjectKindNumericExtensions.IsCustomerReceipt` fasst genau diese sieben Arten zusammen. `ReceiptWebServiceBL.ForwardReceipt` und `CanForwardReceiptsInto` realisieren die Belegweiterführung.
Aussage: Das System soll den Verkaufsprozess über die sieben Kundenbelegarten Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift und Vertrag abbilden und die Weiterführung eines Belegs in einen Folgebeleg unterstützen.
Ergebnis: Aus einem Beleg lassen sich Folgebelege mit Positionsübernahme erzeugen; die Herkunft bleibt über Positionsverknüpfungen nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:273-287 (`IsCustomerReceipt`) – Begründung: Definiert normativ die Menge der Kundenbelegarten.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2315-2336 (`CanForwardReceiptsInto`, `ForwardReceipt`) – Begründung: Belegt die implementierte Weiterführungslogik inkl. Übernahmeoptionen.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ (Unterordner `Offers`, `Orders`, `DeliveryLists`, `Invoices`, `PickupLists`, `CreditVouchers`, `ContractLists`) – Begründung: Je Belegart existieren Kopf-, Positions- und Versionsentitäten.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:307-315 (`GetAssetName`: „Angebot", „Auftrag", „Lieferschein", „Abholschein", „Rechnung", „Gutschrift", „Vertrag", „Stammblatt") – Begründung: Fachliche deutsche Benennung der Belegarten im UI.
Prüfidee: Angebot anlegen, in Auftrag weiterführen, Auftrag in Lieferschein, Lieferschein in Rechnung; nach jedem Schritt muss der Ursprungsbeleg die verarbeitete Menge (`QuantityProcessed`) erhöht haben.
Tracelinks: SyRS-014, SyRS-018, SwRS-004, SwRS-009
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Beschaffungsprozess mit Lieferantenbelegen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Einkauf)
Vorbedingung: Ein Lieferant (Kreditor) ist angelegt.
Fakt: `IsSupplierReceipt` umfasst Anfrage (`SupplierOffer = 15`), Bestellung (`SupplierOrder = 7`), Wareneingang (`SupplierDeliveryList = 8`), WE-Kalkulation (`SupplierInvoice = 18`) und Lieferantengutschrift (`SupplierCreditVoucher = 148`). Für jede Art existieren eigene Entitäten unter `Entities/Sales/Receipts/Supplier*` sowie eigene Nummernkreise (`NumberGroupEnum.Inquiry`, `PurchaseOrder`, `Intake`, `VendorInvoice`, `SupplierCreditVoucher`).
Aussage: Das System soll den Beschaffungsprozess über die fünf Lieferantenbelegarten Anfrage, Bestellung, Wareneingang, WE-Kalkulation und Lieferantengutschrift abbilden.
Ergebnis: Bestellungen, Wareneingänge und Lieferantenrechnungen sind als eigenständige, nummerierte Belege gespeichert und miteinander referenzierbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:289-301 (`IsSupplierReceipt`) – Begründung: Normative Definition der Lieferantenbelegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:40-55 und 106-117 – Begründung: Eigene Nummernkreise mit Zuordnung zu den Tabellen `AnfrKopf`, `BestKopf2`, `WareKopf`, `KalkKopf`, `LiGutKopf`.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:139-147 (Descriptions „Bestellung", „Wareneingang", „WE-Kalkulation", „Li.-Gutschrift") – Begründung: Fachliche Benennung im UI.
Prüfidee: Bestellung anlegen und in einen Wareneingang überführen; die Bestellnummer muss aus dem Nummernkreis `PurchaseOrder` (Tabelle `BestKopf2`, Feld `Nummer`) stammen.
Tracelinks: SyRS-015, SyRS-019, SyRS-024
Konsolidierung: Kandidat: StRS-005 (Kunden- und Lieferantenbelege teilen sich `ReceiptBase`, unterscheiden sich aber in Persistenz und Nummernkreisen)
Status: belegt
```
```
ID: StRS-007
Titel: Vertragsgeschäft mit wiederkehrender Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertragsverwaltung), Hintergrunddienst
Vorbedingung: Ein Vertrag (`ReceiptContract`) ist mit Abrechnungsintervall und Kalkulationsart angelegt und aktiv.
Fakt: `AutomaticFacturaBL.GetActiveContracts` selektiert Verträge mit `State == 1` und wertet `CalculationKind` (`ContractCalculationKind.Auto`, `Need`, manuell), `AutomatedProlongation`, `FirstPaidDate`, `LastPaidDate`, `ContractBegin`, `ContractEnd`, `BillingIntervalKind`/`BillingIntervalDuration` sowie `ContractExtraKind` (`Easy`, `ClickDevice`, `Contingent`) aus. `ContractCloseService` und `ContractEndeService` laufen täglich.
Aussage: Das System soll Verträge mit definiertem Abrechnungsintervall führen und daraus periodisch Rechnungen erzeugen, wobei automatische, bedarfsgesteuerte und manuelle Abrechnungsarten sowie Kontingent- und Klickverträge unterschieden werden.
Ergebnis: Zum Abrechnungslauf werden genau die fälligen Verträge selektiert und in Rechnungen überführt; das Abrechnungsergebnis wird protokolliert (`StoreBillingResult`).
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845 (`GetActiveContracts`) – Begründung: Enthält die vollständige, durchgesetzte Selektionsregel für fällige Verträge.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:2101-2118 (`StoreBillingResult`) – Begründung: Belegt die verpflichtende Protokollierung jedes Abrechnungsergebnisses.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ContractCloseService.cs:32 und ContractEndeService.cs:22 (`TimeSpan.FromDays(1)`) – Begründung: Tagesgenauer Zyklus der vertragsbezogenen Hintergrundverarbeitung.
- [KONTEXT] docs/reference/receipts/contracts-backend.md – Begründung: Beschreibt Kontingentverwaltung, Klickzählerverträge und automatische Verlängerung.
Prüfidee: Vertrag mit `BillingIntervalKind = Monthly`, `BillingIntervalDuration = 1`, `AutomatedBilling = true` und `FirstPaidDate` in der Vergangenheit anlegen; `SearchBillingContracts` mit `IsActiveOnly = false` muss den Vertrag genau einmal je fälliger Periode liefern.
Tracelinks: SyRS-022, SwRS-032
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Ticketgestützter Servicebetrieb (Helpdesk)
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Servicetechniker, Disponent), Web-Account
Vorbedingung: Der Benutzer besitzt das Recht `SHOW_HELPDESK`; Ticketstatus, -typen und -kategorien sind als Stammdaten gepflegt.
Fakt: Tickets werden in `hlpdsk_requests` geführt (Nummernkreis `NumberGroupEnum.Helpdesk`) und besitzen konfigurierbare Status (`HelpdeskStateI3D`), Prioritäten, Typen sowie Haupt- und zwei Unterkategorien. Der Abschlussstatus ist nicht hart kodiert, sondern über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfigurierbar. Der Rechtekatalog `UserRightsConst.Sales.Customer.Helpdesk` umfasst u. a. Anzeigen, Anlegen, Bearbeiten, Abschließen, Fälligkeit ändern, Zeiten bearbeiten, Sichtbarkeit ändern, Checklisten und Ticketvorlagen.
Aussage: Das System soll Serviceanfragen als Tickets mit frei konfigurierbarem Statusmodell, Kategorisierung, Verantwortlichkeiten und Fälligkeitsterminen führen und den Zugriff darauf über eigene Rechte steuern.
Ergebnis: Jedes Ticket ist eindeutig nummeriert, einem Kunden und einem Status zugeordnet und dokumentiert Bearbeiter, Verantwortlichen und Historie.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:418-466 (`CheckUserRigths`) – Begründung: Zeigt die durchgesetzte Rechteprüfung inkl. konfigurierbarem Abschlussstatus.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:12-120 – Begründung: Vollständiges Ticket-Datenmodell mit Status, Priorität, Typ, Kategorien, Fälligkeit, Verantwortlichem und Zeitsummen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:30-31, 100-103 – Begründung: Eigener Nummernkreis „Helpdesk" auf Tabelle `hlpdsk_requests`.
- [KONTEXT] CentronRights.md:3-130 – Begründung: Beschreibt für jedes Helpdesk-Recht die beabsichtigte fachliche Wirkung in Prosa.
Prüfidee: Benutzer ohne `CLOSE_REQUEST` versucht, ein Ticket auf den in den Einstellungen als „geschlossen" markierten Status zu setzen; der Speichervorgang muss mit „Sie haben nicht das Recht \"Helpdesk abschließen\"." scheitern.
Tracelinks: SyRS-035, SyRS-036, SwRS-043, SwRS-044
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Leistungszeiterfassung und Fakturierung von Servicezeiten
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Servicetechniker), Interner Benutzer (Fakturierung)
Vorbedingung: Ein Ticket existiert; dem erfassenden Mitarbeiter ist ein Mitarbeiterartikel zugeordnet.
Fakt: `HelpdeskTimer`/`HelpdeskTimerBase` bilden Zeiterfassungssätze mit Abrechnungszustand (`HelpdeskTimerBillingState`), Zeitartentypen (`HelpdeskTimerTypes`), Stundensatzzuschlägen (`HelpdeskTimerHourlySurchargeRateOverlap`) und Unterschrift ab. `HelpdeskCompact` führt getrennte Summen für berechenbare, nicht berechenbare, geplante, bereits fakturierte und noch nicht fakturierte Zeiten. `TimerBillingBL` realisiert die Überführung in Belege. Das Verschieben oder Löschen einer Zeit ist laut Rechtebeschreibung nur zulässig, solange das Ticket nicht Teil eines Belegs ist.
Aussage: Das System soll erfasste Servicezeiten je Ticket nach Berechenbarkeit und Abrechnungszustand differenzieren und die Überführung berechenbarer Zeiten in Fakturabelege unterstützen; bereits fakturierte Zeiten dürfen nicht mehr verschoben oder gelöscht werden.
Ergebnis: Fakturierte Zeiten sind gegen Veränderung geschützt; offene berechenbare Zeiten sind pro Kunde/Ticket abrechenbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90 (`HasCalculableTimes`, `CalculableTimesInSeconds`, `NotBilledCalculableNotPlannedTimesInSeconds`, `BilledCalculableNotPlannedTimesInSeconds`) – Begründung: Datenmodell trennt berechenbare von nicht berechenbaren und fakturierte von nicht fakturierten Zeiten.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/TimerBilling/TimerBillingBL.cs – Begründung: Eigene Geschäftslogik zur Fakturierung von Zeiten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs:556 (Rechteprüfung `DELETE_HELPDESK_TIMER`) – Begründung: Löschen von Zeiten ist rechtebewehrt.
- [KONTEXT] CentronRights.md:59-66 („Helpdeskzeiten verschieben … aber nur, wenn das Ticket nicht Teil eines Receipts ist") – Begründung: Beschreibt die beabsichtigte Schutzregel gegen Änderung fakturierter Zeiten.
Prüfidee: Eine Zeit fakturieren und anschließend versuchen, sie auf ein anderes Ticket zu verschieben; der Vorgang muss abgewiesen werden.
Tracelinks: SyRS-035, StRS-008
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – die Sperre „bereits fakturierte Zeiten dürfen nicht mehr verschoben oder gelöscht werden" ist nur über `CentronRights.md` (KONTEXT) belegt und im gelesenen Code nicht verifiziert; siehe HYP-004
```
```
ID: StRS-010
Titel: Lagerbestandsführung mit Seriennummern- und Barcodeverfolgung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Lager, Versand)
Vorbedingung: Artikel sind im Artikelstamm angelegt; mindestens ein Lager (`Stock`) existiert.
Fakt: `ReceiptArticleBookingBL.BookArticles` bucht bei jedem Belegspeichern die Mengendifferenz je Artikelposition; `ValidateArticleWarehouses` prüft für Nebenlager, ob der Artikel dort geführt wird, und meldet andernfalls „Den Artikel '{ArticleCode}' gibt es nicht im Lager '{Caption}'." `ReceiptBarcodeBL` (98 KB) verwaltet belegbezogene Barcodes/Seriennummern; `CheckIfAllNonActiveBarcodesAreStillInTheReceipt` verhindert das Entfernen bereits verarbeiteter Barcodes.
Aussage: Das System soll Lagerbestände je Artikel und Lager führen, bei Belegbuchungen automatisch fortschreiben und seriennummern-/barcodepflichtige Artikel positionsgenau verfolgen.
Ergebnis: Der Lagerbestand entspricht nach jeder Belegspeicherung der Summe der gebuchten Mengendifferenzen; einmal zugeordnete, verarbeitete Barcodes können nicht mehr aus dem Beleg entfernt werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:81-96, 171-236 (`BookArticles`, `BookArticlesForItem`) – Begründung: Enthält die durchgesetzte Mengendifferenz-Buchungslogik.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:125-156 (`ValidateArticleWarehouses`) – Begründung: Durchgesetzte Nebenlagerprüfung vor der Buchung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3667-3674 (`CheckIfAllNonActiveBarcodesAreStillInTheReceipt`) – Begründung: Schutzregel gegen Entfernen verarbeiteter Barcodes.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:149 (Fehlertext) – Begründung: Fachliche Formulierung der Lagerzuordnungsregel.
Prüfidee: Lieferschein mit Artikel im Nebenlager erzeugen, bei dem der Artikel dort nicht geführt wird; das Speichern muss mit der genannten Fehlermeldung scheitern.
Tracelinks: SyRS-019, SwRS-030, SwRS-031
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Gesetzeskonformer elektronischer Rechnungsversand
Ebene: StRS
Typ: Schnittstelle / Compliance
Akteur: Interner Benutzer (Fakturierung), Rechnungsempfänger, Finanzbuchhaltung
Vorbedingung: In den Rechnungseinstellungen ist ein ZUGFeRD-/XRechnung-Profil aktiviert.
Fakt: `ZugferdKind` definiert sechs Formatstufen von `ZUGFeRD_1_0` bis `ZUGFeRD_XInvoice_3_0_1`; die Anzeigetexte nennen explizite Gültigkeitszeiträume („XRechnung 2.2 (gültig ab 01.08.2022)", „XRechnung 3.0.1 | ZUGFeRD 2.3.3 & 2.4 & 2.5 (gültig ab 07.05.2025)"). `InvoiceZugferdBL` setzt je Format die KoSIT-Guideline-IDs (`urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0` etc.) und erzeugt PDF/A-3-konforme Dokumente mit eingebetteter `factur-x.xml`.
Aussage: Das System soll Ausgangsrechnungen zusätzlich als strukturierte elektronische Rechnung im ZUGFeRD-/XRechnung-Format erzeugen und dabei das jeweils vom Betreiber konfigurierte, gesetzlich gültige Profil verwenden.
Ergebnis: Zur Rechnung existiert ein PDF/A-3-Dokument mit eingebetteter, gegen die gewählte Guideline-ID validierbarer XML-Rechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289 (Guideline-IDs je `ZugferdKind`) – Begründung: Belegt die formatgenaue Normkonformität im Code.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:167-228 (`CreateZugferdConformPdfDocument`, `PdfZugferdVersion`, `PdfZugferdConformanceLevel.EN16931`, Dateiname `factur-x.xml`) – Begründung: Belegt PDF/A-3-Einbettung und Konformitätsstufe.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:31-44 – Begründung: UI-Auswahlliste mit gesetzlichen Gültigkeitsdaten, belegt den Compliance-Bezug.
- [SEKUNDÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2394-2446 (`GetReceiptInvoiceSettings`) – Begründung: Konfigurationsschalter für Format, Archivierung und XML-Anhang an E-Mails.
- [KONTEXT] docs/guides/development/xrechnung.md, docs/reference/zugferd-feldzuordnung-anwender.md – Begründung: Verweise auf die offizielle FeRD-/KoSIT-Spezifikation.
Prüfidee: Rechnung mit aktivem Profil `ZUGFeRD_XInvoice_3_0_1` exportieren und die eingebettete `factur-x.xml` mit dem KoSIT-Validator gegen XRechnung 3.0 prüfen; das Ergebnis muss fehlerfrei sein.
Tracelinks: SyRS-023, SwRS-045
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Übergabe an die Finanzbuchhaltung
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Buchhaltung), Steuerberater
Vorbedingung: Buchungsrelevante Belege (Rechnungen, Gutschriften, Lieferantenrechnungen) liegen abgeschlossen vor.
Fakt: `BookKeepingExportBL` stellt `ExportCustomerBookingDataFile` und `NewExportSupplierBookingDataFile` bereit und erzeugt über `GetDatevOnlinePackageForExport(BookKeepingReceipt file, string pdfFileName, DateTime startFinancialYear)` ein DATEV-Online-Paket. Im WPF-Client existieren die Module `DataExchange.BookKeeping` und `DataExchange.DatevOnline2020`.
Aussage: Das System soll Debitoren- und Kreditorenbuchungsdaten in einem von der Finanzbuchhaltung einlesbaren Format exportieren und dabei DATEV-Online-Pakete inklusive Belegbild unterstützen.
Ergebnis: Für einen gewählten Zeitraum liegt eine Exportdatei bzw. ein DATEV-Paket mit Buchungssätzen und zugehörigen Beleg-PDFs vor.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs:832 (`ExportCustomerBookingDataFile`), :1437 (`NewExportSupplierBookingDataFile`), :1560 (`GetDatevOnlinePackageForExport`) – Begründung: Implementierte Exportpfade für beide Buchungskreise inkl. DATEV.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:51,53 (Modulregistrierungen `DataExchange.BookKeeping`, `DataExchange.DatevOnline2020`) – Begründung: Belegt die Bedienbarkeit als eigenständige Anwenderfunktion.
Prüfidee: Buchhaltungsexport für einen Monat mit mindestens einer Rechnung ausführen; die erzeugte Datei muss je Rechnung genau einen Buchungssatz enthalten.
Tracelinks: SyRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Forderungsmanagement mit Mahnstufen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Debitorenbuchhaltung)
Vorbedingung: Es existieren offene, überfällige Rechnungen.
Fakt: `DunningBL` aggregiert offene Rechnungen nach vier Mahnstufen (`DunningLevel.None`, `Level1`, `Level2`, `Level3`) und berechnet je Stufe Anzahl und Bruttobetrag als `GrossPriceComplete - PayedGrossAmount - CreditVoucherGrossAmount`. Ein Mahnstopp ist je Kunde und je Rechnung mit Zeitraum (`DunningStopBegin`, `DunningStopEnd`) und Begründung (`DunningInfo`) setzbar.
Aussage: Das System soll überfällige Forderungen in vier Mahnstufen führen, den offenen Betrag um Zahlungen und Gutschriften bereinigt ermitteln und einen befristeten Mahnstopp je Kunde oder je Rechnung zulassen.
Ergebnis: Ein Mahnlauf berücksichtigt ausschließlich Rechnungen ohne aktiven Mahnstopp und weist je Kunde die höchste erreichte Mahnstufe aus.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231 – Begründung: Definiert die vier Mahnstufen und die Berechnung des offenen Bruttobetrags.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431 (`UpdateDunningStopAndInfo`) – Begründung: Belegt Mahnstopp mit Zeitraum auf Kunden- und Belegebene.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/Invoices/Dunning/ (`DunningRunForCustomer`, `DunningRunItem`, `InvoiceDunning`, `CreditVoucherDunning`) – Begründung: Eigenes Datenmodell für Mahnläufe.
Prüfidee: Rechnung mit Mahnstopp im aktuellen Zeitraum versehen; sie darf im Mahnlauf nicht selektiert werden.
Tracelinks: SyRS-037, SwRS-033
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: EDI-Anbindung an IT-Distributoren
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Einkauf), Distributor/Lieferant, Hintergrunddienst
Vorbedingung: Für den Lieferanten ist eine EDI-Konfiguration mit Format, Dokumentart und Verbindungsdaten hinterlegt.
Fakt: `SupplierEdiBL` (118 KB) ist als Partial-Class-Verbund je Lieferantenformat organisiert (`SupplierEdiBL.Also.cs`, `.AlsoCH.cs`, `.Alltron.cs`, `.Herweck.cs`, `.Komsa.cs`, `.Opentrans.cs`). Der `EdiDownloadService` läuft alle 30 Minuten. Gateway-Bibliotheken existieren unter `src/backend/Centron.Gateway/EDI_EGIS` u. a.
Aussage: Das System soll Auftragsbestätigungen, Lieferavise und Rechnungen von IT-Distributoren automatisiert abrufen, formatabhängig einlesen und mit den eigenen Bestellungen abgleichen.
Ergebnis: Eingelesene Distributordokumente aktualisieren die zugehörige Bestellung; jeder Verarbeitungsvorgang ist protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs (Hauptklasse) sowie die formatbezogenen Partial-Dateien im selben Verzeichnis – Begründung: Implementierte Formatvielfalt je Distributor.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37 (`Task.Delay(TimeSpan.FromMinutes(1))`, Intervall 30 Minuten) – Begründung: Belegt den automatisierten, unbeaufsichtigten Abruf.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:148 (`Purchasing.EDIManagement`) – Begründung: EDI-Konfiguration ist eine Anwenderfunktion.
- [KONTEXT] docs/reference/edi/edi-architecture.md – Begründung: Beschreibt Formate (`OpenTrans21`, `Also`, `AlsoCH`, `Herweck`, `Komsa`, `Alltron`, `Zugferd`), Dokumentarten und Verarbeitungsablauf.
Prüfidee: EDI-Testdatei im OpenTrans-2.1-Format für eine bestehende Bestellung einspielen; die bestätigten Mengen und Liefertermine müssen an der Bestellposition erscheinen und ein Logeintrag mit Status `DownloadOK` entstehen.
Tracelinks: SyRS-024, SwRS-046
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Revisionssichere Nachvollziehbarkeit von Belegänderungen
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Zuverlässigkeit / Wartbarkeit; Compliance)
Akteur: Interner Benutzer, Wirtschaftsprüfer
Vorbedingung: Ein Beleg wurde mindestens einmal gespeichert.
Fakt: `ReceiptBase` führt `Version`, `CreatedByI3D`/`CreatedAt`/`CreatedThroughApplicationVersion` und `ChangedByI3D`/`ChangedAt`/`ChangedThroughApplicationVersion`/`ChangedThroughApplication`. Beim Speichern einer neuen Version ruft `ReceiptBL.SaveReceipt` `SaveReceiptVersion(receipt, previousReceiptVersion)`, wodurch der Vorzustand in die Versionstabelle kopiert wird. `ReceiptLogBL` (74 KB) schreibt feldgenaue Änderungseinträge, z. B. `CreateSetAsPaidEntry`, `CreateContingentValueEntry`.
Aussage: Das System soll jede Belegversion vollständig archivieren und fachlich relevante Feldänderungen mit Zeitpunkt, Benutzer und erzeugender Anwendungsversion protokollieren.
Ergebnis: Zu jedem Beleg ist jede frühere Version rekonstruierbar; Änderungen an abrechnungsrelevanten Feldern sind einzeln nachweisbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:46-52 (Audit-Felder) – Begründung: Datenmodell erzwingt die Erfassung von Urheber, Zeitpunkt und Anwendungsversion.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3595-3634 (Setzen der Audit-Felder, `SaveReceiptVersion`) – Begründung: Durchgesetzte Fortschreibung bei jedem Speichervorgang.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369 (`WriteReceiptLogs`) – Begründung: Feldgenaue Änderungsprotokollierung für Kontingentfelder.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:83-121, 147-204 – Begründung: Beschreibt Versionstabellen als 1:1-Kopien und das gemeinsame Logtabellenkonzept (`AnlageLog` mit `AnlageArt`).
Prüfidee: Beleg zweimal mit unterschiedlichen Positionswerten speichern; in `AngKopfVersions`/`AngPosVersions` (bzw. der jeweiligen Belegart) muss der Vorzustand vollständig vorliegen und `Version` inkrementiert sein.
Tracelinks: SyRS-016, SyRS-031, SwRS-007, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Wahrnehmung von DSGVO-Betroffenenrechten
Ebene: StRS
Typ: Sicherheit / Compliance
Akteur: Administrator (Datenschutzbeauftragter)
Vorbedingung: Der Benutzer besitzt das Recht `DsgvoModule.DSGVO_DELETE_CONTACT` bzw. `ACCESS_CLEANUP_DATABASE`; das DSGVO-Modul ist lizenziert.
Fakt: `DataSecurityBL` bietet `DsgvoDeleteRightGetContacts` und `DsgvoDeleteRightDeleteContacts` mit vorgeschalteter Rechteprüfung. Gelöschte Kontakte werden nicht physisch entfernt, sondern mit dem Text `"DSGVO: Auf Anfrage gelöscht. (Durchgeführt von {0} am {1:d} um {1:t} Uhr)"` überschrieben und deaktiviert. Für Kunden, Lieferanten und Accounts sind die Löschpfade `DoDeleteCustomer`, `DoDeleteSupplier`, `DoDeleteAccount` mit `throw new NotImplementedException(...)` versehen; die zugehörigen SQL-Anweisungen stehen auskommentiert im Quelltext.
Aussage: Das System soll dem Löschbegehren betroffener Personen durch rechtebewehrte Anonymisierung von Ansprechpartnerdaten nachkommen und den Vorgang mit ausführendem Benutzer und Zeitpunkt dokumentieren.
Ergebnis: Personenbezogene Felder des Kontakts sind durch den Anonymisierungstext ersetzt und der Datensatz ist deaktiviert; ein Löschprotokoll wird erzeugt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:377-380, 787-790 (Rechteprüfungen) – Begründung: Durchgesetzte Zugriffsbeschränkung auf die Löschfunktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 (`DsgvoDeletedContactMessage`, `DsgvoDeletedContactMessageWithEmployeeInfo`) – Begründung: Belegt Anonymisierung statt physischer Löschung inkl. Nachweis des Ausführenden.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:856-858, 935-937, 996-998 (`NotImplementedException`) – Begründung: Belegt, dass die Löschung auf Kunden-, Lieferanten- und Accountebene nicht produktiv verfügbar ist.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:12 (`Administration.DSGVO`) – Begründung: Eigenes Anwendermodul.
Prüfidee: DSGVO-Löschung für einen Ansprechpartner ausführen; Name und Kommunikationsdaten müssen anschließend den Anonymisierungstext tragen und `Status` auf 0 stehen. Für einen Kunden muss der Aufruf reproduzierbar mit `NotImplementedException` fehlschlagen.
Tracelinks: SyRS-038, SwRS-047
Konsolidierung: nein
Status: belegt; Workaround – für Kunden/Lieferanten/Accounts ist die Löschung nicht implementiert und muss in der Validierung priorisiert geprüft werden
```
```
ID: StRS-017
Titel: Anbindung an Unternehmens-Identitätsverwaltung und Zwei-Faktor-Authentifizierung
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Betreiber hat in `WebServiceConfig.xml` bzw. den Anwendungseinstellungen ein Anmeldeverfahren gewählt.
Fakt: `AuthenticatorFactory` unterstützt `SystemAuthenticationMethod.None | Basic | ActiveDirectory | OpenIdConnect` und wählt anhand von `AppUser.AuthentificationKind` einen Fallback-Authenticator. `WebServiceConfig` enthält `ActiveDirectoryAuthEnabled`, `ActiveDirectoryUrl`, `TwoFactorAuthEnabled`, `TwoFactorAuthType` (Standardwert `RadiusServer`), `RadiusServerAddress`, `MailTwoFactorAuthSenderAddress`, `TwoFactorValidDurationInDays`. `BasicAuthenticator` ruft nach erfolgreicher Kennwortprüfung zwingend `TwoFactorAuthBL.ValidateTwoFactor` auf.
Aussage: Das System soll die Benutzeranmeldung wahlweise gegen den lokalen Benutzerstamm, ein Active Directory oder einen OpenID-Connect-Provider durchführen und optional eine Zwei-Faktor-Authentifizierung per RADIUS oder E-Mail erzwingen.
Ergebnis: Eine Anmeldung ist nur erfolgreich, wenn das konfigurierte Primärverfahren und – falls aktiviert – der zweite Faktor bestanden werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:99-147 – Begründung: Vollständige, durchgesetzte Verfahrensauswahl inkl. Lizenz- und Aktivierungsprüfungen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 – Begründung: Zwei-Faktor-Prüfung ist zwingender Teil der Basic-Anmeldung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:7-32 – Begründung: Konfigurationsschalter für AD, RADIUS und Mail-2FA mit Zeitgrenzen.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md – Begründung: Betriebsanleitung für die OIDC-Anbindung.
Prüfidee: `TwoFactorAuthEnabled = true` mit RADIUS setzen; eine Anmeldung mit korrektem Kennwort, aber ohne gültigen zweiten Faktor muss mit `DefaultMessageCodes.TwoFactorAuthFailed` und der Meldung „Die Zwei-Faktor-Authentifizierung ist fehlgeschlagen." abgewiesen werden.
Tracelinks: SyRS-003, SyRS-006, SwRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Unbeaufsichtigte Hintergrundverarbeitung
Ebene: StRS
Typ: funktional / betrieblich
Akteur: Administrator, Hintergrunddienst
Vorbedingung: Der Web-Service läuft und `ExecuteServices` ist aktiviert.
Fakt: Der Web-Service betreibt 33 Hintergrunddienste (Verzeichnis `src/webservice/Centron.Host/AspNetCore/HostedServices`), darunter EDI-Download, automatische Preisaktualisierung, Vertragsabschluss, Eskalationen, Erinnerungen, Datenqualitätspflege, Volltextindizierung, Massenupdates, Telemetrie. Jeder Dienst deklariert über `GetExecutionInterval()` sein Intervall (Sekunden bis 30 Tage) und lässt sich über `BackgroundServiceBL.IsServiceEnabled(serviceName)` einzeln abschalten.
Aussage: Das System soll wiederkehrende fachliche und technische Aufgaben ohne Benutzerinteraktion in definierten Zeitintervallen ausführen und jede dieser Aufgaben zentral aktivierbar bzw. deaktivierbar halten.
Ergebnis: Jeder Dienst führt seine Aufgabe im hinterlegten Intervall aus; Start- und letzte Laufzeit sind persistiert (`UpdateStartTime`, `UpdateLastRunTime`).
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94 – Begründung: Gemeinsame Ausführungsschleife mit Aktivierungsprüfung und Laufzeitpersistenz.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (33 Dienstklassen mit `GetExecutionInterval`) – Begründung: Belegt Umfang und Taktung der automatisierten Verarbeitung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:18 (`<ExecuteServices>false</ExecuteServices>`) – Begründung: Betrieblicher Hauptschalter für die Diensteausführung.
- [KONTEXT] docs/Background Service/DataQualityService.md – Begründung: Beschreibt Zweck und Aufgabenliste eines der Dienste.
Prüfidee: Einen Dienst über `BackgroundServiceBL` deaktivieren; im Log darf innerhalb von 60 Sekunden nach Cachablauf nur noch „… is disabled, skipping execution." erscheinen.
Tracelinks: SyRS-025, SyRS-026, SwRS-034, SwRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-019
Titel: Deutsch als Primärsprache der Bedienoberfläche
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Gebrauchstauglichkeit)
Akteur: Interner Benutzer, Web-Account
Vorbedingung: keine
Fakt: Fehlermeldungen der Geschäftslogik sind durchgängig deutsch formuliert (z. B. „Der Beleg hat kein gültiges Datum.", „Sie haben nicht genügend Rechte um die Gruppe einer anderen Filiale zu löschen.", „Die maximale Anzahl an Lizenzen wurde erreicht."). Lokalisierte Texte liegen als `LocalizedStrings.resx` (deutsch, Basisdatei) und `LocalizedStrings.en.resx` (englisch) vor; es wurden 14 `.resx`-Dateien gefunden.
Aussage: Das System soll alle benutzersichtbaren Texte primär in deutscher Sprache bereitstellen und Englisch als zusätzliche Oberflächensprache unterstützen.
Ergebnis: Ein Benutzer ohne Sprachumstellung erhält ausschließlich deutschsprachige Beschriftungen und Meldungen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3565, 3577 (deutsche Fehlertexte im Code) – Begründung: Deutsche Texte sind fest im Geschäftslogikpfad verankert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:357, 360, 382, 389 – Begründung: Weitere hart kodierte deutsche Fehlermeldungen.
- [SEKUNDÄR] `LocalizedStrings.resx` / `LocalizedStrings.en.resx` (Ressourcendateien der Projekte) – Begründung: Zweisprachiges Ressourcenmodell mit Deutsch als Basis.
- [KONTEXT] docs/getting-started/general-structure.md:114-141 („German-First Language Policy") – Begründung: Explizite Entwicklungsvorgabe.
Prüfidee: Client mit englischer Systemsprache starten; nicht in `LocalizedStrings.en.resx` übersetzte Texte müssen als deutscher Basistext erscheinen (kein Platzhalter, kein Fehler).
Tracelinks: SyRS-028, SwRS-051
Konsolidierung: nein
Status: belegt; Workaround – ein Teil der Meldungen ist hart kodiert statt lokalisiert und ist daher nicht umschaltbar
```
```
ID: StRS-020
Titel: Online-Banking-Anbindung und Zahlungszuordnung
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Buchhaltung), Bank/Zahlungsdienstleister
Vorbedingung: Eine finAPI-Zugangskonfiguration ist hinterlegt und eine Bankverbindung ist verknüpft.
Fakt: `Centron.APIs.FinAPI` kapselt die finAPI-Schnittstelle mit getrennten Sandbox- und Live-Endpunkten (`https://sandbox.finapi.io`, `https://live.finapi.io`, jeweils zugehörige WebForm-URLs) und OAuth-Client-Credentials- bzw. Client-Password-Grant. `OnlineBankingAccountTransactionsBL` (67 KB) verarbeitet Kontoumsätze; `IncomingPaymentBL` verarbeitet Zahlungseingänge; das Recht `Controlling.Finances.INCOMING_PAYMENT_TRANSACTIONS` steuert den Zugriff.
Aussage: Das System soll Kontoumsätze über einen Bankenaggregator (finAPI) abrufen und diese offenen Rechnungen als Zahlungseingang zuordnen können.
Ergebnis: Zugeordnete Zahlungen setzen den bezahlten Betrag (`PaidFC`) der Rechnung und ändern bei Vollzahlung deren Zustand.
Belege:
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16 – Begründung: Belegt die konkrete Fremdschnittstelle mit Sandbox-/Live-Trennung.
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/RestClient/RestClientBase.cs:145-147 (OAuth-Grant-Typen, `client_secret`) – Begründung: Belegt das Authentifizierungsverfahren gegenüber der Bankschnittstelle.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4920-4958 (`SetAsPaid`-Pfad mit Recht `INCOMING_PAYMENT_TRANSACTIONS`, `PaidFC`, Zustandswechsel) – Begründung: Verknüpft Zahlungseingang mit Belegzustand und Protokollierung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:140 (`OnlineBanking.ConfigurationSettings`) – Begründung: Konfigurierbares Anwendermodul.
Prüfidee: Kontoumsatz mit dem Bruttobetrag einer offenen Rechnung zuordnen; die Rechnung muss anschließend `PaidFC` = Bruttobetrag und `State = Completed` aufweisen, und `ReceiptLog` muss einen `SetAsPaid`-Eintrag enthalten.
Tracelinks: SyRS-014, SyRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-021
Titel: Belegdruck, PDF-Erzeugung und revisionsfeste Ablage
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer
Vorbedingung: Der Beleg ist einem Dokumentenordner (`DirectoryI3D`) zugeordnet und eine Reportgruppe ist konfiguriert.
Fakt: `ReceiptBL.AddReportPdf` legt das erzeugte PDF im Belegordner ab; der Dateiname folgt der Vorlage `"{Belegart} {NUMBER} V{VERSION}.pdf"` oder einem konfigurierten `ReportGroup.CustomExportFilename`. Vor der Ablage prüft `GetIdenticalDocumentInDirectory(directoryI3D, name, reportPdf, receipt.Version)`, ob ein bytegleiches Dokument derselben Version bereits existiert, und gibt in diesem Fall das bestehende Dokument zurück (Kommentar: „Ticket 160276: Avoid storing identical report PDFs multiple times."). Reports werden mit FastReport erzeugt (`FastReport.Net.Pro` unter Windows, `FastReport.Core.Skia` plattformneutral).
Aussage: Das System soll zu jedem Beleg ein versionsbezogenes PDF erzeugen, es im Belegordner ablegen und dabei die mehrfache Ablage inhaltsgleicher Dokumente derselben Belegversion vermeiden.
Ergebnis: Je Belegversion und Report existiert höchstens ein PDF-Dokument im Belegordner.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3459-3503 (`AddReportPdf`, `GetReportAttachmentNameTemplate`) – Begründung: Enthält Ablageregel, Dublettenprüfung und Namenskonvention.
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (PackageReferences `FastReport.Net.Pro`, `FastReport.Core.Skia`) – Begründung: Belegt die eingesetzte Reportengine und die Windows-/Linux-Trennung.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3476 (Kommentar mit Ticketnummer 160276) – Begründung: Weist die Dublettenprüfung als nachträgliche Fehlerbehebung aus.
Prüfidee: Denselben Beleg in derselben Version zweimal als PDF exportieren; im Belegordner darf nur ein Dokument entstehen und beide Aufrufe müssen dieselbe Dokument-I3D liefern.
Tracelinks: SyRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Provisionsermittlung für den Vertrieb
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertriebsleitung)
Vorbedingung: Ein Provisionsschema ist definiert und einem Kunden bzw. Mitarbeiter zugeordnet.
Fakt: Es existieren die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`, `ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionEmployeeGoal`, `ReceiptProvisionEmployeeLevel` und `ReceiptProvisionItemEntity`. `ReceiptProvisionBL` (45 KB) reichert Belege beim Laden über `FillReceiptWithProvision` mit Provisionsdaten an. Der Hintergrunddienst `UpdateExpiredProvisionSchemasService` läuft stündlich. Ein eigener Rechtebereich `UserRightsConst…Provision` existiert.
Aussage: Das System soll Vertriebsprovisionen anhand mitarbeiter- und kundenbezogener Provisionsschemata mit Zielvorgaben und Stufen belegbezogen ermitteln.
Ergebnis: Zu jedem provisionsrelevanten Beleg liegen Provisionsdatensätze je Position vor; abgelaufene Schemata werden automatisch fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs (6 Entitäten) – Begründung: Vollständiges Provisionsdatenmodell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7246-7255 (`FillReceiptWithAdditionalData` → `FillReceiptWithProvision`) – Begründung: Provisionsdaten sind fester Bestandteil des geladenen Belegs.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs:45 – Begründung: Automatisierte Pflege abgelaufener Schemata.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:82-84 (`Finances.Receipts.Provision.*`) – Begründung: Eigene Anwendermodule für Schema, Zuordnung und Auswertung.
Prüfidee: Beleg mit einem Artikel speichern, für den ein Provisionsschema greift; `ReceiptProvisionItemEntity` muss genau einen Datensatz je provisionsrelevanter Position enthalten.
Tracelinks: SyRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: RMA- und Reparaturabwicklung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Service, Lager)
Vorbedingung: Ein Gerät oder Artikel wurde vom Kunden zurückgesandt bzw. soll an den Lieferanten zurückgehen.
Fakt: `RmaBL` (108 KB) verwaltet die Objektarten `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145` und `RmaArticle = 40`. Eigene Nummernkreise bestehen für `RMANumber` (Tabelle `RMA`), `Repairing` (`dbo.Rma`), `RepairEntrance` (`dbo.RmaSendForth`) und `Reshipment` (`dbo.RmaSendBack`). `ReceiptBL.CheckCloseRMADeliverylistReceipt` schließt einen Lieferschein automatisch ab, wenn er RMA-Positionen enthält und der Anwender die Rückfrage bejaht.
Aussage: Das System soll Rücksendungen und Reparaturen kunden- und lieferantenseitig als eigenständige, nummerierte Vorgänge führen und deren Abschluss mit der Lieferscheinabwicklung verknüpfen.
Ergebnis: Ein RMA-Vorgang besitzt eine eigene Nummer; ein aus RMA erzeugter Lieferschein kann ohne Folgerechnung abgeschlossen werden (`ClosedThroughRMA = true`).
Belege:
- [PRIMÄR] src/backend/Centron.BL/CustomerArea/RmaBL.cs – Begründung: Zentrale Geschäftslogik des RMA-Prozesses.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180 (`CheckCloseRMADeliverylistReceipt`) – Begründung: Durchgesetzte Verknüpfung von RMA und Lieferscheinabschluss.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:22-29, 128-133 – Begründung: Getrennte Nummernkreise für Reparatur, Reparatureingang und Rücksendung.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4169-4171 (Dialogtext „Soll der Lieferschein abgeschlossen werden? Falls der Kunde keine Rechnung erhalten soll klicken Sie 'Ja'.") – Begründung: Erläutert die fachliche Bedeutung des Abschlusses.
Prüfidee: Lieferschein mit einer RMA-verknüpften Position speichern und die Abschlussfrage bejahen; der Beleg muss `State = Completed` und `ClosedThroughRMA = true` aufweisen.
Tracelinks: SyRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Betrieb als verteiltes Client-Server-System mit optionaler Containerbereitstellung
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit)
Akteur: Administrator
Vorbedingung: Ein Microsoft SQL Server ist erreichbar.
Fakt: Die Lösung besteht aus einem WPF-Windows-Client (`Centron.WPF.UI`, `net10.0-windows`), einem plattformneutralen Web-Service (`Centron.Host`, `net10.0`, wahlweise als Konsolenanwendung oder Windows-Dienst) und einer Blazor-Webanwendung (`CentronNexus`, `CentronNexus.Host`). `Centron.BL` wird für beide Zielplattformen gebaut (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>`). Eine `compose.yaml` definiert die Dienste `db` (MSSQL), `webservice`, `smtp` und `nexus`; für den Web-Service existiert ein Linux-Dockerfile.
Aussage: Das System soll als verteiltes System aus Windows-Fachclient, plattformneutralem Anwendungsserver und Webanwendung betrieben werden können, wahlweise als Windows-Installation oder als Containerverbund unter Linux.
Ergebnis: Web-Service und Webanwendung sind ohne Windows-Abhängigkeit lauffähig; der Fachclient bleibt Windows-gebunden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>` mit plattformabhängigen PackageReferences, u. a. `SkiaSharp.NativeAssets.Linux`) – Begründung: Belegt die bewusste Doppelzielplattform.
- [PRIMÄR] docker/compose/compose.yaml:1-54 – Begründung: Definiert die vollständige Betriebstopologie inkl. Portzuordnungen.
- [PRIMÄR] src/centron/Centron.WPF.UI/Centron.WPF.UI.csproj (`<TargetFramework>net10.0-windows</TargetFramework>`) – Begründung: Belegt die Windows-Bindung des Fachclients.
- [KONTEXT] docs/guides/services/web-service-on-linux.md – Begründung: Betriebsanleitung für den Linux-Betrieb.
Prüfidee: `docker compose up` ausführen; Web-Service (Port 4321) und Nexus (Port 8050) müssen erreichbar sein und Nexus muss sich am Web-Service anmelden können.
Tracelinks: SyRS-040, SwRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Preisfindung mit kunden- und vertragsspezifischen Sonderkonditionen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertrieb)
Vorbedingung: Für Artikel, Kunde oder Vertrag sind Sonderpreise bzw. Staffelpreise gepflegt.
Fakt: `ReceiptItemPriceBL` wertet in dieser Reihenfolge aus: Vertragssonderpreis (`ContractSpecialPrice` mit `Kind` ∈ {`FixedPrice`, `ChangePurchasePrice`, `ChangeRecommendedSellPrice`, `ChangeSellPrice`, `ChangeListPrice`} und `ChangeKind` ∈ {`Fixed`, `Percentage`}), andernfalls Kundensonderpreis (`CustomerSpecialPrice` mit `SpecialPriceKind` ∈ {`SurchargePurchasePrice`, `ReduceRecommendedSellPrice`, `FixedPrice`, `ReduceSellPrice`, `ReduceListPrice`}), andernfalls Staffelpreis (`ArticleVolumePrices`, nur wenn `UseVolumePrice(contractI3D)`). Ein Kommentar hält fest, dass Vertragswerte invertiert sind („10 is 10 % surcharge, -10 is 10 % discount").
Aussage: Das System soll den Verkaufspreis einer Belegposition in fester Vorrangfolge aus Vertragssonderpreis, Kundensonderpreis und Mengenstaffel ermitteln, wobei sowohl absolute als auch prozentuale Auf- und Abschläge auf unterschiedliche Preisbasen möglich sind.
Ergebnis: Der ermittelte Positionspreis entspricht der höchstrangigen zutreffenden Konditionsregel; ohne Kondition gilt der Artikelstandardpreis.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266 – Begründung: Enthält die vollständige, durchgesetzte Vorrangfolge und alle Konditionsarten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:261-266, 365 (`UseVolumePrice`, `GetArticleVolumePrice`) – Begründung: Staffelpreise greifen nur nachrangig und nur unter Bedingung.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:181 (Kommentar zur Vorzeicheninversion) – Begründung: Erklärt eine nicht selbsterklärende Datenkonvention, die bei einer Migration erhalten oder bewusst geändert werden muss.
- [KONTEXT] docs/reference/receipts/actionprice-system.md – Begründung: Ergänzende Beschreibung des Aktionspreissystems.
Prüfidee: Für einen Artikel gleichzeitig Vertragssonderpreis (fest 100 €), Kundensonderpreis (fest 120 €) und Staffelpreis (90 € ab 10 Stück) hinterlegen; eine Position über 10 Stück im Vertragskontext muss 100 € ergeben.
Tracelinks: SyRS-021, SwRS-029
Konsolidierung: Kandidat: SwRS-029 (mehrere Preisquellen mit gleicher fachlicher Funktion „Sonderkondition"; Vereinheitlichung im Zielsystem prüfen)
Status: belegt
```
@@ -0,0 +1,896 @@
# SyRS – System Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Ebene:** System Requirements (ISO/IEC/IEEE 29148:2018, Kap. 9.3)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Erstellt:** 2026-08-25 · Reverse Requirements Engineering, rein statische Analyse
Belegklassifikation und Feldsemantik siehe `StRS.md`, Abschnitt 0. Alle Pfade sind relativ zum
Wurzelverzeichnis der Codebasis. Nicht-funktionale Anforderungen tragen zusätzlich die Zuordnung
zu einem Qualitätsmerkmal nach **ISO/IEC 25010**.
---
## 1. Authentifizierung, Sitzung und Lizenzierung
```
ID: SyRS-001
Titel: Ticketbasierte Authentifizierung am Web-Service
Ebene: SyRS
Typ: Sicherheit
Akteur: Alle Clientanwendungen
Vorbedingung: Der Client kennt Benutzername, Kennwort und die Lizenz-GUID seiner Anwendung.
Fakt: `Authenticator.GetTicket()` authentifiziert den Benutzer, ermittelt über `ApplicationKind.GetKindByLicenseGuid(Auth.ApplicationName)` die aufrufende Anwendung und gibt bei Erfolg eine Ticket-ID zurück. Jeder geschützte Web-Service-Aufruf trägt dieses Ticket im `Request.Ticket`-Feld (WCF-Bridge) bzw. als `Authorization: Bearer <ticket>` oder Query-Parameter `access_token` (ASP.NET-Core-Pfad) und wird durch `AuthenticationTicketBL.GetAuthTicketInfo(token, ipAddress, apiMethod)` validiert. Ist die Anwendungs-GUID unbekannt, wird mit `DefaultMessageCodes.ApplicationIDUnknown` abgewiesen.
Aussage: Das System soll den Zugriff auf Web-Service-Funktionen ausschließlich nach Vorlage eines gültigen, serverseitig geführten Sitzungstickets gewähren, das an Benutzer, Anwendung und Gerät gebunden ist.
Ergebnis: Aufrufe ohne oder mit ungültigem Ticket werden mit `StatusCode.InvalidTicket` bzw. `AuthenticateResult.Fail` abgewiesen; gültige Aufrufe werden ausgeführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:94-155 (`GetTicket`, `AuthenticateUser`) – Begründung: Vollständiger, durchgesetzter Ticket-Ausstellungspfad inkl. Anwendungserkennung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:63-101 – Begründung: Zentrale Ticketprüfung vor jedem attributierten Web-Service-Aufruf.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:44-95, 104-144 – Begründung: Zweiter Prüfpfad für das ASP.NET-Core-Authentifizierungsschema mit Header- und Query-String-Übergabe.
Prüfidee: Web-Service-Methode ohne Ticket aufrufen; Antwort muss `Status = InvalidTicket` und die Meldung „You need to provide a ticket for the method '<Name>'." enthalten.
Tracelinks: StRS-002, SwRS-022, SwRS-026, SwRS-027
Konsolidierung: Kandidat: SwRS-026/SwRS-027 (zwei parallele Ticketprüfpfade – WCF-Bridge und ASP.NET-Core-Handler – mit gleicher fachlicher Funktion)
Status: belegt
```
```
ID: SyRS-002
Titel: Zeitliche Begrenzung und Verlängerung des Sitzungstickets
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Sicherheit)
Akteur: Alle Clientanwendungen
Vorbedingung: Ein gültiges Ticket wurde ausgestellt.
Fakt: `TicketBL` definiert `TicketExpireInMinutes = 30` (Standard), `TicketMonitoringConnectorExpireInMinutes = 5` (Monitoring-Konnektoren) und `TicketExpire24HoursInMinutes = 1440` (Anwendungen mit `ExpirationKind.OneDay`). Für `ExpirationKind.FromSettings` gilt `Math.Max(Einstellung TicketReleaseTime, 30)`. `RefreshTicketExpireDate` verlängert das Ticket nur, wenn das neue Ablaufdatum mindestens 5 Minuten nach dem bisherigen liegt; ein Kommentar benennt die daraus folgenden Randfälle. `DeleteExpiredTickets` entfernt abgelaufene Tickets.
Aussage: Das System soll Sitzungstickets nach einer anwendungsabhängigen Frist von 5 Minuten bis 24 Stunden ungültig werden lassen und sie bei Aktivität verlängern, wobei die Verlängerung aus Performanzgründen erst ab 5 Minuten Differenz geschrieben wird.
Ergebnis: Ein inaktives Ticket verfällt spätestens nach der anwendungsspezifischen Frist; ein aktiv genutztes Ticket bleibt gültig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:26-28, 136-164 (`GetExpireDate`) – Begründung: Enthält alle Ablauffristen und deren Zuordnung zu `ExpirationKind`.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:113-134 (`RefreshTicketExpireDate`) – Begründung: Durchgesetzte 5-Minuten-Schreibschwelle.
- [KONTEXT] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:117-127 (Kommentarblock zu den Randfällen) – Begründung: Dokumentiert die bewusst in Kauf genommene Fehlerklasse „Ticket verfällt früher als erwartet" und verweist auf die Retry-Logik der Clients.
Prüfidee: Ticket ausstellen, 31 Minuten ohne Aufruf warten, danach einen Aufruf absetzen; er muss mit `InvalidTicket` abgewiesen werden.
Tracelinks: StRS-002, SwRS-022
Konsolidierung: nein
Status: belegt; Workaround – die 5-Minuten-Schwelle erzeugt laut Codekommentar einen bekannten Randfall vorzeitigen Ticketverfalls
```
```
ID: SyRS-003
Titel: Konfigurierbares Anmeldeverfahren mit Fallback
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Administrator
Vorbedingung: In den Anwendungseinstellungen ist eine `SystemAuthenticationMethod` gesetzt.
Fakt: `AuthenticatorFactory.GetAuthenticatorWithSystemAuth` wählt anhand von `SystemAuthenticationMethod` (`None`, `Basic`, `ActiveDirectory`, `OpenIdConnect`) einen Haupt-Authenticator. Bei `None` entscheidet `WebServiceConfigHelper.Current.ActiveDirectoryAuthEnabled`. Zusätzlich wird pro Benutzer `AppUser.AuthentificationKind` ausgewertet: Bei `CentronLogin` wird ein `FallbackAuthenticator` mit `BasicAuthenticator` als Rückfallebene gebildet; bei `WindowsAuth` bzw. `OpenIdConnectAuth` ein `FailingAuthenticator` mit der Meldung, dass das Verfahren fehlkonfiguriert ist.
Aussage: Das System soll das Anmeldeverfahren systemweit konfigurierbar machen und je Benutzer ein abweichendes, am Benutzerdatensatz hinterlegtes Verfahren berücksichtigen; ist ein benutzerspezifisches Verfahren serverseitig nicht verfügbar, soll die Anmeldung mit einer erklärenden Meldung scheitern statt stillschweigend auf ein schwächeres Verfahren zurückzufallen.
Ergebnis: Benutzer mit `AuthentificationKind = CentronLogin` können sich auch bei aktivem AD/OIDC lokal anmelden; Benutzer mit AD-/OIDC-Bindung erhalten bei fehlender Serverkonfiguration eine Fehlkonfigurationsmeldung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:54-117 – Begründung: Vollständige Verfahrensauswahl inklusive Fallback-Konstruktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:203-207 (`GetAuthenticationKindFromUserName`) – Begründung: Belegt die benutzerindividuelle Verfahrenszuordnung.
- [SEKUNDÄR] `LocalizedStrings.AuthenticatorFactory_FallbackMisconfiguredErrorMessage` (referenziert in AuthenticatorFactory.cs:74, 80) – Begründung: Fachliche Formulierung des Fehlkonfigurationsfalls.
Prüfidee: Benutzer mit `AuthentificationKind = WindowsAuth` bei deaktiviertem Active Directory anmelden; die Anmeldung muss mit der Fehlkonfigurationsmeldung scheitern und nicht per Basic-Anmeldung gelingen.
Tracelinks: StRS-017, SwRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-004
Titel: Kennwortprüfung des lokalen Benutzerstamms
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Anmeldeverfahren `Basic` bzw. Fallback auf `BasicAuthenticator`.
Fakt: `BasicAuthenticator.AuthenticateInternal` berechnet `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` und sucht einen `AppUser` mit `Name == UserName && Password == decodedPassword`. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. Leere Benutzername- oder Kennworteingaben werden vorab mit `DefaultMessageCodes.NoUsernameOrPassword` abgewiesen. Jeder Versuch wird über NLog protokolliert (`Logger.Info` bei Erfolg, `Logger.Warn` bei Fehlschlag, jeweils mit `RequestId`, Benutzername und Kontext).
Aussage: Das System soll Kennwörter des lokalen Benutzerstamms als SHA-1-Hashwert speichern und vergleichen; da kein benutzerindividueller Zufallswert (Salt) verwendet wird, ist dieses Verfahren nach heutigem Stand nicht ausreichend und in der Zielarchitektur zu ersetzen.
Ergebnis: Bei Übereinstimmung von Benutzername und Kennworthash wird der Benutzer authentifiziert, andernfalls mit `DefaultMessageCodes.LoginFailed` abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50 – Begründung: Zeigt Hashverfahren, fehlenden Salt und den Datenbankvergleich unmittelbar im durchgesetzten Anmeldepfad.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:37-43 – Begründung: Durchgesetzte Vorabprüfung auf leere Anmeldedaten.
- [KONTEXT] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:48 (`// TODO the password should be salted!!!`) – Begründung: Das Entwicklungsteam kennzeichnet die Implementierung selbst als unzureichend.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:477-483 (`HashToken` mit `SHA256`) – Begründung: Gegenbeleg – im neueren Access-Token-Modul wird bereits SHA-256 verwendet; die Schwäche betrifft ausschließlich den Altpfad der Benutzerkennwörter.
Prüfidee: Zwei Benutzer mit identischem Kennwort anlegen; in der Tabelle `Sichbenu` müssen beide denselben `Password`-Wert tragen. Genau dieses Verhalten muss im Zielsystem ausgeschlossen sein.
Tracelinks: StRS-017, SwRS-024
Konsolidierung: Kandidat: SwRS-024 (zwei unterschiedliche Hashverfahren für dieselbe fachliche Funktion „Geheimnis prüfen"; Vereinheitlichung auf ein modernes Verfahren erforderlich)
Status: belegt; Workaround – ungesalzenes SHA-1, laut Quelltextkommentar bekannte Altlast; in der Migration mit hoher Priorität zu ersetzen
```
```
ID: SyRS-005
Titel: Deaktivierung von Benutzerkonten über mehrere unabhängige Kriterien
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Ein Benutzerdatensatz existiert.
Fakt: `Authenticator.ValidateAppUser` verweigert die Anmeldung, wenn (a) `AppUser.IsAccountDisabled` gesetzt ist, (b) das heutige Datum im Sperrzeitraum `AccountDisabledFromDate`/`AccountDisabledToDate` liegt oder (c) `EmployeeBL.IsActiveEmployeeCompact(user.Employee)` fehlschlägt (Prüfung auf Einstellungs- und Austrittstermin). In allen drei Fällen wird `DefaultMessageCodes.EmployeeAccountDeactivated` mit der Meldung „Mitarbeiterkonto wurde deaktiviert" zurückgegeben; der konkrete Grund wird ausschließlich ins Log geschrieben.
Aussage: Das System soll ein Benutzerkonto sperren, sobald es manuell deaktiviert wurde, sich in einem hinterlegten Sperrzeitraum befindet oder der zugehörige Mitarbeiter nach Einstellungs-/Austrittsdatum nicht aktiv ist, und dem Anmeldenden dabei keine Auskunft über den konkreten Sperrgrund geben.
Ergebnis: Anmeldung wird abgewiesen; das Serverlog enthält den auslösenden Grund.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:157-218 (`ValidateAppUser`) – Begründung: Enthält alle drei Sperrkriterien und die einheitliche, nicht auskunftsgebende Fehlermeldung.
- [SEKUNDÄR] `LocalizedStrings.UsersBL_AuthenticateAppUser_MitarbeiterKontoWurdeDeaktiviert` – Begründung: Einheitlicher Meldungstext für alle Sperrgründe.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:176-177 (Logtext „…deactivated through the checkbox 'User hat Account in c-entron'") – Begründung: Benennt das zugehörige UI-Element und damit die fachliche Bedienung.
Prüfidee: Mitarbeiter mit Austrittstermin in der Vergangenheit anlegen; die Anmeldung muss mit `EmployeeAccountDeactivated` scheitern, obwohl das Konto nicht manuell deaktiviert wurde.
Tracelinks: StRS-002, StRS-017
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-006
Titel: Zwei-Faktor-Authentifizierung über RADIUS oder E-Mail
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: `TwoFactorAuthEnabled = true` in der Web-Service-Konfiguration.
Fakt: Nach erfolgreicher Kennwortprüfung ruft `BasicAuthenticator` zwingend `TwoFactorAuthBL.ValidateTwoFactor(userName, password, loggedInUser, applicationName, machineName)` auf; schlägt dies fehl, wird mit `DefaultMessageCodes.TwoFactorAuthFailed` abgewiesen. Es existieren die Validierer `RadiusTwoFactorValidator` (mit eigenem `RadiusClient` und `RadiusPaketParser`) und `EmailTwoFactorValidator` hinter der Schnittstelle `ITwoFactorValidator`. Konfigurierbar sind `TwoFactorAuthType` (Standard `RadiusServer`), `RadiusServerAddress`, `RadiusServerSecret` (verschlüsselt abgelegt), `RadiusServerConnectionTimeoutInSeconds` (Standard 30), `MailTwoFactorAuthTimeoutInSeconds` (Standard 120) und `TwoFactorValidDurationInDays`.
Aussage: Das System soll bei aktivierter Zwei-Faktor-Authentifizierung nach erfolgreicher Kennwortprüfung einen zweiten Faktor über einen RADIUS-Server oder per E-Mail-Einmalcode prüfen und die Anmeldung ohne diesen Faktor verweigern.
Ergebnis: Nur Anmeldungen mit bestandenem zweiten Faktor erhalten ein Ticket; die Gültigkeit des zweiten Faktors kann für eine konfigurierbare Anzahl Tage bestehen bleiben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 – Begründung: Der zweite Faktor ist nicht optional umgehbar, sondern Teil des Anmeldepfads.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/ (`ITwoFactorValidator`, `RadiusTwoFactorValidator`, `EmailTwoFactorValidator`, `RadiusClient`, `RadiusPaketParser`, `TwoFactorAuthBL`) – Begründung: Beide Verfahren sind vollständig implementiert.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:23-32 – Begründung: Konfigurationsschalter und Zeitgrenzen.
Prüfidee: Mail-2FA aktivieren und den Einmalcode 121 Sekunden nach Anforderung eingeben; die Anmeldung muss wegen Zeitablaufs scheitern.
Tracelinks: StRS-017, SyRS-003
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-007
Titel: Lizenz- und Kontingentprüfung bei der Anmeldung
Ebene: SyRS
Typ: Sicherheit / funktional
Akteur: Alle Clientanwendungen, Lizenzgeber
Vorbedingung: Der Benutzer wurde erfolgreich authentifiziert.
Fakt: `Authenticator.AuthenticateUser` gibt ein bereits bestehendes Ticket für dieselbe Kombination aus Anwendung, Benutzer, Web-Account und Gerät unverändert zurück, ohne Lizenz zu verbrauchen. Erst wenn kein Ticket existiert, ruft es `LicenseManager.CheckLicense(applicationKind, appVersion, user)`. Dort wird je Lizenz-GUID geprüft: Versionsgültigkeit (`CheckLicenseVersion`) und, falls ein Benutzer übergeben wurde, ob `TicketBL.GetTicketCount(license, app.LicenseUsageKind, user) >= GetLicenseCount(license)`; in diesem Fall wird `DefaultMessageCodes.LicenseMaximumReached` mit der Meldung „Die maximale Anzahl an Lizenzen wurde erreicht." gemeldet. Die Zählweise unterscheidet `LicenseUsageKind.PerUser` und `PerUserAndPerMachine`.
Aussage: Das System soll die Anzahl gleichzeitiger Anmeldungen je Produkt gegen das Lizenzkontingent prüfen und bestehende Sitzungen desselben Benutzers auf demselben Gerät nicht erneut auf das Kontingent anrechnen.
Ergebnis: Bei erschöpftem Kontingent erhält der Anmeldende die Lizenzmeldung; bestehende Sitzungen bleiben unberührt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:124-142 – Begründung: Zeigt die Reihenfolge „bestehendes Ticket vor Lizenzprüfung" und die Serialisierung über `lock`.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:270-302 (`CheckLicense`) – Begründung: Enthält Versions- und Kontingentprüfung sowie das Verhalten bei mehreren zulässigen Lizenz-GUIDs (Erfolg genügt bei einer).
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45,53 (`licenseUsageKind: LicenseUsageKind.PerUser` für Service-Board) – Begründung: Belegt die produktabhängige Zählweise.
Prüfidee: Lizenz mit `count = 1` einspielen und von zwei verschiedenen Geräten anmelden; die zweite Anmeldung muss `LicenseMaximumReached` liefern, die Wiederanmeldung vom ersten Gerät hingegen gelingen.
Tracelinks: StRS-004, SwRS-020, SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-008
Titel: Anwendungsbezogene Rechte- und Sperrprüfung beim Login
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Systemintegrator
Vorbedingung: Der Benutzer ist authentifiziert und die aufrufende Anwendung ist über ihre Lizenz-GUID erkannt.
Fakt: `Authenticator.ValidateRights(applicationKind, user)` verweigert die Ticketausstellung, wenn die Anwendung ein `DisallowingRight` definiert und der Benutzer dieses besitzt, oder wenn sie ein `RequiredRight` definiert und der Benutzer dieses nicht besitzt. Beispiele: `ServiceBoard` und `ServiceBoardNext` mit `disallowingRight: RIGHT_DISALLOW_SERVICEBOARD_LOGIN (20800073)`; `RiversuiteInventory`, `RiversuitePro` und `RiversuiteOnline` mit `requiredRight`; `MailScannerNET` mit `requiredRight: ACCESS_VMA_MODULE (20800112)`.
Aussage: Das System soll für einzelne Clientanwendungen den Zugang zusätzlich über ein erforderliches oder ein ausschließendes Benutzerrecht steuern, unabhängig von der Lizenz.
Ergebnis: Der Anmeldeversuch wird mit `DefaultMessageCodes.RightCheckFailed` und dem Anwendungsnamen abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:68-86 (`ValidateRights`) – Begründung: Durchgesetzte Prüfung vor der Ticketvergabe.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:28,34,36,41,44,45,53,58-61 – Begründung: Konkrete Zuordnung der Rechte-IDs zu Anwendungen; die IDs sind bewusst als lokale Konstanten dupliziert („// Taken from UserRightsConst").
Prüfidee: Benutzer das Recht 20800073 zuweisen und Anmeldung am Service-Board versuchen; die Anmeldung muss mit `RightCheckFailed` scheitern.
Tracelinks: StRS-002, StRS-004, SwRS-020
Konsolidierung: Kandidat: SwRS-018 (Rechte-IDs sind in `ApplicationKind.cs` dupliziert statt aus `UserRightsConst` referenziert)
Status: belegt; Workaround – vier Rechte-IDs sind als lokale Konstanten kopiert und laufen bei Änderungen auseinander
```
```
ID: SyRS-009
Titel: API-Zugriff über persönliche Access Tokens
Ebene: SyRS
Typ: Schnittstelle / Sicherheit
Akteur: API-Client (technisch)
Vorbedingung: Die Lizenz `LicenseGuids.AccessTokenModule` liegt vor; ein Token wurde für einen Mitarbeiter ausgestellt.
Fakt: `AccessTokenBL.CreatePersonalToken` erzeugt einen Zufallstoken, speichert ausschließlich dessen SHA-256-Hash (`TokenHash`) und gibt den Klartext genau einmal zurück („only available once during creation"). `ValidateToken(plainToken, ipAddress, apiMethod)` prüft Lizenz, Hashübereinstimmung, `IsActive` und schreibt einen Eintrag über `AccessTokenLogBL`. Tokens besitzen ein optionales Ablaufdatum (`ExpiresAt`) und werden logisch gelöscht (`IsDeleted`). Die Anzahl aktiver, nicht abgelaufener Tokens ist gegen die Lizenzanzahl begrenzt. Im `AuthenticateInterceptor` unterliegen Access Tokens ausdrücklich keiner Anwendungsbeschränkung.
Aussage: Das System soll Maschinen-zu-Maschinen-Zugriffe über persönliche, lizenzpflichtige Access Tokens zulassen, deren Klartext nur bei der Erstellung sichtbar ist und deren Verwendung protokolliert wird.
Ergebnis: Ein gültiger Token authentifiziert den Aufruf; jede Verwendung erzeugt einen Logeintrag mit IP-Adresse und aufgerufener Methode.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:154-186 (Erzeugung, Hashbildung, Kollisionsbehandlung) – Begründung: Belegt die Einweg-Speicherung des Geheimnisses.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:377-400, 477-483 (`ValidateToken`, `HashToken` mit SHA-256) – Begründung: Prüf- und Hashverfahren.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:436-451 (Kontingentprüfung gegen Lizenzanzahl) – Begründung: Lizenzgebundene Mengenbegrenzung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:51-58 (Kommentar „Access tokens don't have application restrictions") – Begründung: Belegt die abweichende, weniger restriktive Prüfung gegenüber Tickets.
Prüfidee: Token erzeugen, Klartext notieren, Detailansicht erneut öffnen; der Klartext darf nicht erneut abrufbar sein. Token deaktivieren und einen API-Aufruf absetzen; er muss abgewiesen werden.
Tracelinks: StRS-004, SwRS-024, SwRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-010
Titel: Methodenbezogene Anwendungsbeschränkung von Web-Service-Aufrufen
Ebene: SyRS
Typ: Sicherheit
Akteur: Systemintegrator, Clientanwendungen
Vorbedingung: Der Aufruf erfolgt mit gültigem Ticket.
Fakt: `AuthenticateInterceptor` liest das `AuthenticateAttribute` der aufgerufenen Methode aus. Ist `attribute.Applications` nicht leer und die Anwendung des Tickets nicht enthalten, wird der Aufruf mit `StatusCode.Failed` und der Meldung „You don't have the permission to execute the method '<Name>'." abgewiesen. Ist das Ticket an einen Web-Account gebunden und `attribute.AllowWebAccountLogin == false`, wird ebenfalls abgewiesen. Ein Quelltextkommentar hält fest, dass die Umkehrung („diese Anwendung darf nur diese Methoden aufrufen") nicht abgedeckt ist.
Aussage: Das System soll je Web-Service-Methode einschränken können, welche Clientanwendungen sie aufrufen dürfen und ob Web-Account-Anmeldungen zugelassen sind.
Ergebnis: Nicht zugelassene Anwendungen und Web-Accounts erhalten eine Berechtigungsfehlermeldung, ohne dass die Methode ausgeführt wird.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:29-48 – Begründung: Durchgesetzte Prüfung vor `invocation.Proceed()`.
- [KONTEXT] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:33-37 (deutscher Kommentar zur Lücke) – Begründung: Das Entwicklungsteam benennt die fehlende Gegenrichtung explizit als bekannte Einschränkung.
Prüfidee: Methode mit `AuthenticateAttribute(Applications = [ApplicationKind.Centron])` mit einem Service-Board-Ticket aufrufen; der Aufruf muss abgewiesen werden.
Tracelinks: SyRS-001, StRS-003, SwRS-027
Konsolidierung: nein
Status: belegt; Workaround – laut Codekommentar deckt der Mechanismus nur eine Richtung ab (Methode schränkt Anwendungen ein, nicht Anwendung schränkt Methoden ein)
```
---
## 2. Berechtigungen
```
ID: SyRS-011
Titel: Auflösung von Benutzerrechten über Gruppenzugehörigkeit
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Der Benutzer ist authentifiziert.
Fakt: `AppRightsBL.HasUserRight(appUserI3D, rightID)` ermittelt die Rechte über den Sitzungs-Cache-Schlüssel `AllRightsFromAppUser{appUserI3D}` und die Abfrage `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `CheckRightsFromUser(appUserI3D, rightI3Ds)` liefert die Schnittmenge einer übergebenen Rechteliste. Rechteänderungen werden in `AppRightLog` mit Kind, Objekt, Beschreibung, Urheber, Zeitpunkt und Anwendungsversion protokolliert.
Aussage: Das System soll das Vorliegen eines Rechts ausschließlich über die Gruppenmitgliedschaft des Benutzers bestimmen und das Ergebnis je Sitzung zwischenspeichern.
Ergebnis: Rechteprüfungen liefern innerhalb einer Sitzung konsistente Ergebnisse; Änderungen an Rechten wirken erst in der Folgesitzung bzw. nach Cache-Invalidierung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:644-664 – Begründung: Enthält Cache-Schlüssel und die maßgebliche SQL-Abfrage.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:95-111 (`CheckRightsFromUser`) – Begründung: Zweiter, ungecachter Prüfpfad für Rechtelisten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-781 (`WriteBaseLog`) – Begründung: Audit aller Rechteänderungen.
Prüfidee: Innerhalb einer laufenden Sitzung ein Recht entziehen; die Prüfung muss bis zum Sitzungsende weiterhin `true` liefern und erst nach Neuanmeldung `false`. Dieses Verhalten ist im Zielsystem bewusst zu bestätigen oder zu ändern.
Tracelinks: StRS-002, SwRS-016, SwRS-017
Konsolidierung: Kandidat: SyRS-013 (identische fachliche Funktion für Web-Accounts über `WebAccountsRights`)
Status: belegt
```
```
ID: SyRS-012
Titel: Einschränkende Rechte „nur eigene" und „nur eigene Filiale"
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Der Benutzer besitzt das Basisrecht für die betreffende Objektart.
Fakt: Zusätzlich zu jedem Basisrecht existieren einschränkende Rechte, deren Besitz den Zugriff *verkleinert*, z. B. `SHOW_OFFERS_ONLY_OWN (20400149)`, `SHOW_OFFERS_ONLY_OWN_BRANCH (20400150)`, `CREATE_NEW_OFFER_ONLY_OWN_BRANCH (20400211)`, `EDIT_OFFER_ONLY_OWN_BRANCH (20800028)`, analog für alle sieben Kundenbelegarten. `HelpdeskBL.GetShowHelpdeskRight` bildet daraus die Stufen `All`, `OnlyOwnBranch`, `OnlyOwn`, `OnlyOwnAndNotify`, `None`. `ReceiptBL.CanUserEditReceipt` und `CanUserCreateReceiptsInBranch` setzen die Filialbeschränkung durch; `BranchBL.IsBranchEqual` behandelt „keine Filiale" und Filial-ID 0 als gleichwertig.
Aussage: Das System soll den Datenzugriff über einschränkende Rechte auf die eigenen Datensätze oder die eigene Filiale begrenzen, wobei der Besitz eines einschränkenden Rechts die Wirkung des Basisrechts reduziert.
Ergebnis: Ein Benutzer mit einschränkendem Recht sieht bzw. bearbeitet ausschließlich die zugelassene Teilmenge und erhält andernfalls `RightCheckFailed`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295 (`CanUserEditReceipt`) – Begründung: Durchgesetzte Zweistufenprüfung Basisrecht + Filialbeschränkung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10270 (`CanUserCreateReceiptsInBranch`) – Begründung: Behandlung von Standardfiliale (null bzw. 0) als Sonderfall.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:255-291 (`ShowHelpdeskRight`-Ableitung) – Begründung: Vollständige Stufenlogik für Tickets.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2192-2213 (Offer-Rechteblock) – Begründung: Belegt das Muster Basisrecht + zwei Einschränkungsrechte je Belegart.
- [KONTEXT] CentronRights.md:9-17 („This is a **restricting right**.") – Begründung: Dokumentiert die invertierte Semantik ausdrücklich.
Prüfidee: Benutzer aus Filiale A mit `EDIT_OFFER` und `EDIT_OFFER_ONLY_OWN_BRANCH` versucht, ein Angebot der Filiale B zu speichern; die Aktion muss mit „Der Benutzer hat nicht das Recht Belege vom Typ \"Angebot\" einer anderen Filiale zu bearbeiten." scheitern.
Tracelinks: StRS-001, StRS-002, SwRS-015
Konsolidierung: Kandidat: Das Muster „Basisrecht + ONLY_OWN + ONLY_OWN_BRANCH" ist für sieben Belegarten, Tickets, Kalender, CRM-Projekte und Projektverwaltung nahezu identisch dupliziert; im Zielsystem als generisches Sichtbarkeitskonzept zusammenführbar.
Status: belegt
```
```
ID: SyRS-013
Titel: Getrenntes Rechtemodell für Web-Accounts
Ebene: SyRS
Typ: Sicherheit
Akteur: Web-Account
Vorbedingung: Der Web-Account ist authentifiziert.
Fakt: `AppRightsBL.HasWebAccountRight` und `GetAllWebRightsFromWebAccount` werten `SELECT WebRightsI3D FROM WebAccountsRights WHERE WebAccountsI3D = :WebAccountI3D` aus; der Cache-Schlüssel lautet `AllRightsFromWebAccount{I3D}`. `HelpdeskBL.CheckRights` verzweigt anhand von `LoggedInUser.IsWebAccountLogin` in `CheckWebRights` statt `CheckUserRigths` und prüft dort z. B. `WEBRIGHT_CREATEREQUEST`. Der Rechte-Nummernraum (11000–61007) ist disjunkt zum Mitarbeiterrechteraum.
Aussage: Das System soll für Web-Accounts ein eigenständiges Rechtemodell führen und bei jeder rechtebewehrten Operation anhand der Anmeldeart zwischen Mitarbeiter- und Web-Account-Rechten unterscheiden.
Ergebnis: Ein Web-Account kann ausschließlich die über `WebAccountsRights` freigegebenen Funktionen ausführen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:666-691 – Begründung: Getrennte Auswertung inkl. eigenem Cache.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-416, 468-474 – Begründung: Verzweigung nach Anmeldeart im Speicherpfad eines Tickets.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/WebAccountRightsConst.cs:9-79 – Begründung: Vollständiger, disjunkter Rechtekatalog.
Prüfidee: Web-Account ohne `WEBRIGHT_CREATEREQUEST` versucht, ein Ticket anzulegen; die Aktion muss mit „Der User hat nicht das Recht, Helpdesks anzulegen." scheitern.
Tracelinks: StRS-003, SyRS-011, SwRS-041
Konsolidierung: Kandidat: SyRS-011 (zwei strukturell gleiche Rechtemodelle; Zusammenführung zu einem Rollen-/Berechtigungsmodell im Zielsystem prüfen)
Status: belegt
```
---
## 3. Belegverarbeitung
```
ID: SyRS-014
Titel: Belegzustandsmodell mit drei Zuständen
Ebene: SyRS
Typ: Daten / funktional
Akteur: Interner Benutzer
Vorbedingung: Ein Beleg existiert.
Fakt: `ReceiptState` kennt genau drei Werte: `Active = 1` („offen"), `Completed = 2` („abgeschlossen"), `Canceled = 3` („storniert"). Zustandswechsel sind an konkrete fachliche Ereignisse gebunden, u. a.: Zahlungseingang setzt `Completed`, Zahlungsrücknahme setzt `Active`; ein WE-Kalkulationsbeleg im Zustand `Active` wird nach Anwenderbestätigung auf `Completed` gesetzt; ein RMA-Lieferschein ebenso. Ein Beleg im Zustand `Canceled` kann nicht mehr als bezahlt/unbezahlt markiert werden.
Aussage: Das System soll für jeden Beleg genau einen der drei Zustände offen, abgeschlossen oder storniert führen und Zustandsänderungen ausschließlich über definierte fachliche Ereignisse zulassen; stornierte Belege sind fachlich abschließend und dürfen nicht mehr in Zahlungsvorgänge einbezogen werden.
Ergebnis: Der Belegzustand ist zu jedem Zeitpunkt eindeutig; Aktionen auf stornierten Belegen werden mit einer erklärenden Fehlermeldung abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28 – Begründung: Definiert normativ die drei Zustände und ihre deutschen Bezeichnungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4936-4951 – Begründung: Durchgesetzte Sperre für stornierte Belege und der Zustandswechsel bei Zahlung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4130-4180 (`CheckCloseReceipt`, `CheckCloseRMADeliverylistReceipt`) – Begründung: Zwei weitere, an Anwenderbestätigung gekoppelte Übergänge nach `Completed`.
- [SEKUNDÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:18-27 (`GetReceiptStateString`) – Begründung: Anwendersichtbare Zustandsbezeichnungen.
Prüfidee: Rechnung stornieren und anschließend als bezahlt markieren; der Aufruf muss mit „Der Beleg … wurde stoniert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden." scheitern (Schreibfehler im Original beachten).
Tracelinks: StRS-005, StRS-020, StRS-023, SwRS-012
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-015
Titel: Belegnummernvergabe aus filial- und mandantenbezogenen Nummernkreisen
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer, System
Vorbedingung: Für die Belegart und die Filiale des Belegs existiert ein `NumberGroup`-Datensatz.
Fakt: `NumberGroupEnum` definiert 31 Nummernkreise; jeder ist über `GetTableName()`/`GetFieldName()` fest an eine Tabelle und Spalte gebunden (z. B. `Invoice` → `RechKopf.Nummer`, `Helpdesk` → `hlpdsk_requests.Nummer`, `ArticleCode` → `Artik.ArtikelCode` mit Stringvergleich). `NumberGroupBL.FindNextNumber` bildet `current + interval` und erhöht so lange um `interval`, bis die Nummer in der Zieltabelle nachweislich nicht vergeben ist; für `Customer` und `Supplier` wird zusätzlich gegen `dbo.Kunden` bzw. `dbo.Kreditor` geprüft. `ReceiptBL.UpdateReceiptNumber` wählt den Nummernkreis der Belegfiliale, falls `BranchI3D > 0`, sonst den Mandanten-Nummernkreis.
Aussage: Das System soll Belegnummern je Belegart, Mandant und Filiale aus einem konfigurierbaren Nummernkreis mit Startwert, Intervall und Bereichsgrenzen vergeben und dabei sicherstellen, dass keine bereits vergebene Nummer erneut ausgegeben wird.
Ergebnis: Jede vergebene Nummer ist innerhalb ihrer Zieltabelle eindeutig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:94-134 (`FindNextNumber`) – Begründung: Enthält die durchgesetzte Kollisionsprüfung gegen die Zieltabelle.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:76-197 (`GetTableName`, `GetFieldName`, `GetCompareAsStrings`) – Begründung: Vollständige Zuordnung Nummernkreis → Tabelle/Spalte.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7265-7285 (`UpdateReceiptNumber`) – Begründung: Filial- bzw. mandantenbezogene Auswahl des Nummernkreises.
Prüfidee: In `RechKopf` manuell eine Rechnung mit der nächsten erwarteten Nummer anlegen und anschließend eine Rechnung im System erzeugen; die vergebene Nummer muss die manuell belegte überspringen.
Tracelinks: StRS-001, StRS-005, StRS-006, SwRS-010, SwRS-011
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-016
Titel: Versionierung von Belegen
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer
Vorbedingung: Der Beleg wurde bereits gespeichert.
Fakt: `ReceiptBase.Version` führt eine fortlaufende Versionsnummer. `ReceiptBL.SaveReceipt` akzeptiert nur drei Fälle: erste Version (kein Vorgänger und `Version == 1`), unveränderte Version (`Version == previous.Version`) oder Folgeversion (`Version == previous.Version + 1`); andernfalls bricht der Speichervorgang mit „Der Beleg hat keine gültige Versionsnummer." ab. Bei einer neuen Version wird zuvor `CanUserEditReceipt` geprüft und anschließend `SaveReceiptVersion(receipt, previousReceiptVersion)` ausgeführt; für Belege, die Kundenaktivitäten erzeugen, wird zusätzlich eine Aktivität angelegt.
Aussage: Das System soll fachlich relevante Belegänderungen als neue, lückenlos aufsteigende Belegversion führen und den Vorzustand vollständig archivieren; das Überspringen oder Zurücksetzen von Versionsnummern soll abgewiesen werden.
Ergebnis: Versionsnummern sind je Beleg lückenlos aufsteigend; zu jeder Vorversion existiert ein vollständiger Archivsatz.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578 – Begründung: Explizite, durchgesetzte Versionsnummernvalidierung mit drei zulässigen Fällen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3621-3634 – Begründung: Kopplung von Versionsanlage, Rechteprüfung und Archivierung.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 – Begründung: Beschreibt die Versionstabellen als exakte 1:1-Kopien inklusive `OriginalI3D` und `KopfVersionsI3D`.
Prüfidee: Beleg mit `Version = previous.Version + 2` speichern; der Aufruf muss mit „Der Beleg hat keine gültige Versionsnummer." scheitern.
Tracelinks: StRS-015, SwRS-007, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-017
Titel: Schutz vor konkurrierenden Belegänderungen
Ebene: SyRS
Typ: funktional / nicht-funktional (ISO 25010: Zuverlässigkeit)
Akteur: Interner Benutzer
Vorbedingung: Zwei Benutzer bearbeiten denselben Beleg.
Fakt: Es existieren zwei Mechanismen. (a) Optimistisch: `ReceiptBase.ConcurrencyControlGuid` (Datenbankspalte `GUI3D`) wird in mindestens acht Änderungsmethoden gegen den vom Client übergebenen Wert geprüft; bei Abweichung wird `DefaultMessageCodes.ChangedByOtherInstance` mit „The receipt {I3D} ({Kind}) was changed in the meantime." zurückgegeben. (b) Pessimistisch: `TryLockReceipt`/`UnLockReceipt` sperren einen Beleg für andere Benutzer; beim Anlegen wird bei `autoLockIfNewReceipt = true` automatisch gesperrt.
Aussage: Das System soll konkurrierende Änderungen an demselben Beleg verhindern, indem es den Beleg während der Bearbeitung für andere Benutzer sperrt und zusätzlich beim Schreiben prüft, ob der Beleg zwischenzeitlich verändert wurde.
Ergebnis: Die zweite konkurrierende Änderung wird abgewiesen; der Benutzer erhält den Hinweis auf die zwischenzeitliche Änderung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4808-4809, 4843-4844, 4884-4885, 4939-4940, 4988-4989, 5039-5040, 5272 – Begründung: Sieben Fundstellen derselben optimistischen Prüfung belegen deren systematische Anwendung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3087-3093, 3166-3174, 3915-3917 (`TryLockReceipt`, `UnLockReceipt`) – Begründung: Pessimistische Sperre inkl. automatischer Sperre bei Neuanlage.
- [SEKUNDÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptSearch/*ReceiptSearchConfiguration.cs (`ConcurrencyControlGuid = AK.GUI3D`) – Begründung: Belegt die Abbildung auf die Datenbankspalte `GUI3D` für alle Belegarten.
Prüfidee: Beleg in zwei Sitzungen laden, in Sitzung 1 speichern, danach in Sitzung 2 speichern; der zweite Speichervorgang muss `ChangedByOtherInstance` liefern.
Tracelinks: StRS-015, SwRS-004
Konsolidierung: Kandidat: Die identische GUID-Prüfung ist an sieben Stellen kopiert statt zentral gekapselt.
Status: belegt
```
```
ID: SyRS-018
Titel: Rechteprüfung beim Anlegen und Bearbeiten von Belegen
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Ein Beleg soll gespeichert werden.
Fakt: `ReceiptBL.SaveReceipt` prüft bei neuen Belegen `CanUserCreateNewReceiptsAtCustomerOrSupplier` und `CanUserCreateReceiptsInBranch`, bei neuen Versionen `CanUserEditReceipt`. Jede Prüfung erfolgt innerhalb der umschließenden Transaktion und bricht den gesamten Speichervorgang ab. Die Rechte-IDs stammen belegartspezifisch aus `SpecificLogics` (`HasRightToCreateANewReceiptOnlyOwnBranch`, `HasRightToEditReceipt`, `HasRightToEditReceiptOnlyOwnBranch`, `HasRightToViewReceipt`).
Aussage: Das System soll die Berechtigung zum Anlegen und Ändern eines Belegs serverseitig innerhalb der Speichertransaktion prüfen und den Vorgang bei fehlender Berechtigung vollständig zurückweisen.
Ergebnis: Kein Beleg und keine Belegversion wird persistiert, wenn die Berechtigung fehlt; es entsteht keine Teiländerung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3600-3634 – Begründung: Zeigt die Rechteprüfungen innerhalb von `Session.WithTransaction`.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3544 (`return this.Session.WithTransaction(() => …)`) – Begründung: Belegt die transaktionale Klammer des gesamten Speichervorgangs.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10311 – Begründung: Implementierung der drei Prüfmethoden.
Prüfidee: Benutzer ohne `CREATE_NEW_INVOICE` legt eine Rechnung an; nach dem Fehlschlag darf in `RechKopf` kein neuer Datensatz und in der Nummernkreistabelle keine erhöhte `Current`-Nummer stehen.
Tracelinks: StRS-002, StRS-005, SyRS-012, SwRS-015
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-019
Titel: Automatische Lagerbuchung bei Belegspeicherung
Ebene: SyRS
Typ: funktional
Akteur: System, Interner Benutzer
Vorbedingung: Der Beleg enthält Artikelpositionen mit `ChangeStock = true`.
Fakt: `ReceiptArticleBookingBL.BookArticlesForItem` bucht nur für die Positionsarten `Article`, `CustomerDiscount`, `SupplierFreightNoSplitArticle`, `SupplierInsuranceNoSplitArticle`. Positionen mit `OnlyPriceValue = true` werden übersprungen. Die zu buchende Menge ist die Differenz `(QuantityComplete − QuantityProcessed)` gegenüber dem Vorzustand derselben Position **im selben Lager**; bei Lagerwechsel wird der Vorzustand nicht angerechnet. Ist die Differenz 0, erfolgt keine Buchung. `UnBookArticles` storniert Buchungen für entfernte Positionen, gewechselte Lager und auf `false` gesetztes `ChangeStock`.
Aussage: Das System soll den Lagerbestand bei jeder Belegspeicherung um die Mengendifferenz gegenüber der Vorversion fortschreiben, wobei ein Lagerwechsel als vollständige Aus- und Einbuchung behandelt wird.
Ergebnis: Der Lagerbestand ist nach dem Speichern konsistent mit den Positionsmengen des Belegs; entfernte Positionen sind vollständig ausgebucht.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:171-236 – Begründung: Enthält die vollständige Buchungsregel inklusive Ausschlusskriterien.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:97-123 (`UnBookArticles`) – Begründung: Definiert die drei Stornierungsauslöser.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:180-184 (Kommentar zu `OnlyPriceValue`) – Begründung: Erläutert einen nicht selbsterklärenden Sonderfall bei Gutschriften.
Prüfidee: Position eines gespeicherten Lieferscheins vom Hauptlager auf ein Nebenlager umstellen; das Hauptlager muss die volle Menge zurückerhalten und das Nebenlager die volle Menge abgeben.
Tracelinks: StRS-010, SwRS-030, SwRS-031
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-020
Titel: Datumsabhängige Ermittlung des Mehrwertsteuersatzes
Ebene: SyRS
Typ: funktional
Akteur: System
Vorbedingung: Für den Artikel bzw. die Position ist ein Steuersatz hinterlegt; Steuersätze bilden über `NextTaxRate` eine Kette.
Fakt: `TaxBL.GetTaxRateForReceiptItem(taxRateI3D, receiptDate, articleI3D)` läuft die `NextTaxRate`-Kette bis zum Ende vor und danach rückwärts, solange der Vorgängersatz ein Ablaufdatum besitzt, dessen Datumsanteil `>= receiptDate.Date` ist. Fehlt der Steuersatz, greift die Fallbackkette Artikel → Sekundär-Warengruppe → Warengruppe → Standardsatz des Standardlands. Existieren mehrere Steuersätze mit demselben Folgesatz, wird eine `ResultException` mit ausführlichem deutschem Erklärungstext geworfen.
Aussage: Das System soll den auf eine Belegposition anzuwendenden Mehrwertsteuersatz aus dem Belegdatum und einer als einfache Kette modellierten Steuersatzhistorie bestimmen und eine mehrdeutige Kette als Konfigurationsfehler ablehnen.
Ergebnis: Belege mit historischem Datum werden mit dem damals gültigen Satz berechnet; mehrdeutige Steuersatzketten führen zu einer erklärenden Fehlermeldung statt zu einer stillen Fehlberechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237 (`GetTaxRateForReceiptItem`) – Begründung: Vollständiger, durchgesetzter Ermittlungsalgorithmus.
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:239-284 (`GetDefaultTaxtRateByArticle`, `GetDefaultTaxtRateByCountry`) – Begründung: Definiert die Fallbackreihenfolge.
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:286-320 (`GetPreviousTaxRate` mit `ResultException` bei Mehrdeutigkeit) – Begründung: Durchgesetzte Konsistenzprüfung der Steuersatzkette.
- [SEKUNDÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:302-315 (deutscher Erklärungstext) – Begründung: Fachliche Formulierung der Anforderung an die Steuersatzpflege.
Prüfidee: Steuersatz 16 % mit Ablaufdatum 31.12.2020 und Folgesatz 19 % anlegen; eine Rechnung mit Datum 01.12.2020 muss 16 %, eine mit Datum 01.02.2021 muss 19 % verwenden.
Tracelinks: StRS-005, StRS-011, SwRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-021
Titel: Vorrangfolge der Preisfindung
Ebene: SyRS
Typ: funktional
Akteur: System
Vorbedingung: Eine Artikelposition wird in einen Beleg eingefügt oder neu bewertet.
Fakt: `ReceiptItemPriceBL` prüft zuerst `GetContractSpecialPrice(article, contractI3D)`; nur wenn kein Vertragssonderpreis vorliegt, wird `GetSpecialPrice(article, customer)` ausgewertet; Staffelpreise (`ArticleVolumePrices`) greifen nachrangig und nur, wenn `UseVolumePrice(contractI3D)` wahr ist. Beide Sonderpreisarten unterscheiden fünf Änderungsarten (Festpreis, Aufschlag auf EK, Abschlag auf UVP, Abschlag auf VK, Abschlag auf Listenpreis) und zwei Änderungsmodi (absolut, prozentual). Vertragswerte sind vorzeichenverkehrt hinterlegt.
Aussage: Das System soll den Verkaufspreis einer Position nach der festen Vorrangfolge Vertragssonderpreis vor Kundensonderpreis vor Mengenstaffel ermitteln.
Ergebnis: Der Positionspreis ist bei gegebenem Artikel, Kunde, Vertrag und Menge deterministisch reproduzierbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266 – Begründung: Enthält die durchgesetzte Vorrangfolge als `if/else`-Kaskade.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:181,187,192 (Kommentare „The contract values are inverted") – Begründung: Weist eine migrationskritische Datenkonvention aus.
Prüfidee: Siehe StRS-025.
Tracelinks: StRS-025, SwRS-029
Konsolidierung: Kandidat: SwRS-029
Status: belegt
```
```
ID: SyRS-022
Titel: Selektion fälliger Verträge für den Abrechnungslauf
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer (Vertragsverwaltung)
Vorbedingung: Verträge sind mit Abrechnungsparametern angelegt.
Fakt: `AutomaticFacturaBL.GetActiveContracts` filtert ausschließlich Verträge mit `State == 1` und wertet je nach Modus aus: Anzeigemodus (`IsActiveOnly`) auf Basis von `ContractBegin`/`ContractEnd`/`AutomatedProlongation`; Abrechnungsmodus auf Basis von `CalculationKind`, `LastPaidDate`, `FirstPaidDate` und Stichtag. Anschließend entfernt `SearchBillingContracts` (a) dynamische Bedarfsverträge ohne Sonderartikel, (b) Verträge, die zu einer leeren Rechnung führen würden. Verträge mit fehlenden Stückzahlen, seriennummernpflichtigen oder nicht lieferbaren Artikeln werden markiert (`WithEmptyPos`, `WithBarcode`, `NoDeliverable`).
Aussage: Das System soll für einen Abrechnungsstichtag genau die Verträge selektieren, die nach Vertragslaufzeit, Abrechnungsart und letzter Abrechnung fällig sind, und Verträge ausschließen, die zu einer leeren Rechnung führen würden.
Ergebnis: Der Abrechnungslauf erzeugt keine leeren Rechnungen und keine Doppelabrechnung derselben Periode; problematische Verträge werden dem Anwender markiert zur Prüfung vorgelegt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845 – Begründung: Vollständige Selektionsbedingung im Code.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:881-947 – Begründung: Ausschluss- und Markierungsregeln inklusive deutscher Kommentare („leere RE vermeiden", „Verträge ohne Stückanzahl").
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md – Begründung: Beschreibt die Sonderbehandlung von RMM-Artikeln in der Vertragsabrechnung.
Prüfidee: Vertrag ohne abrechenbare Positionen und ohne Sonderartikel anlegen; er darf im Abrechnungslauf nicht erscheinen.
Tracelinks: StRS-007, SwRS-032
Konsolidierung: nein
Status: belegt
```
---
## 4. Schnittstellen
```
ID: SyRS-023
Titel: Erzeugung elektronischer Rechnungen nach konfiguriertem Profil
Ebene: SyRS
Typ: Schnittstelle
Akteur: System, Rechnungsempfänger
Vorbedingung: In den Rechnungseinstellungen ist ein `ZugferdKind` gesetzt oder wird per Migrationsregel abgeleitet.
Fakt: `ReceiptWebServiceBL.GetReceiptInvoiceSettings` liefert `ActiveZugferdInterface`; ist dieser `None`, wird das Profil aus den Altschaltern `IsZugferdXRechnungActive` und `IsXRechung2Active` abgeleitet (`ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2` oder `ZUGFeRD_XInvoice_2_0`). `InvoiceZugferdBL` verwendet als Standard `ZugferdKind.ZUGFeRD_XInvoice_3_0_1` und setzt die passende PDF/A-Version (`PdfZugferdVersion.Version2_0_1` bzw. `Version2_1`), Konformitätsstufe `EN16931` und den Anhangsnamen `factur-x.xml`. Weitere Schalter steuern Archivierung, XML-Anhang an E-Mails, Bevorzugung des Mandantennamens, Unterdrückung von Artikel- und EAN-Code sowie die Wahl des Ansprechpartners (`ZugferdSellerContactPersonKind`, Standard `Ceo`).
Aussage: Das System soll das E-Rechnungsformat aus einer zentralen Einstellung ableiten, dabei ältere Einzelschalter rückwärtskompatibel interpretieren und die formatabhängigen technischen Parameter automatisch setzen.
Ergebnis: Auch bei nicht gesetzter Neueinstellung wird ein gültiges Profil bestimmt; das erzeugte Dokument entspricht diesem Profil.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2394-2446 – Begründung: Enthält die vollständige Migrationsregel von Altschaltern auf `ZugferdKind`.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:94, 204-228, 1271-1289 – Begründung: Formatabhängige technische Parameter und Guideline-IDs.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:44 (`NewestActiveZugferdVersion`) – Begründung: Zentrale Definition des jeweils aktuellen Profils.
Prüfidee: `ActiveZugferdInterface` leeren und nur `IsZugferdXRechnungActive = true`, `IsXRechung2Active = false` setzen; die Einstellungsabfrage muss `ZUGFeRD_XInvoice_1_2` liefern.
Tracelinks: StRS-011, StRS-012, SwRS-045
Konsolidierung: Kandidat: Drei Einstellungsschalter (`ActiveZugferdInterface`, `IsZugferdXRechnungActive`, `IsXRechung2Active`) bilden dieselbe fachliche Entscheidung ab; im Zielsystem auf einen Schalter zu reduzieren.
Status: belegt; Workaround – die Ableitung aus Altschaltern ist eine Migrationshilfe für historische Konfigurationen
```
```
ID: SyRS-024
Titel: Automatisierter EDI-Import von Lieferantendokumenten
Ebene: SyRS
Typ: Schnittstelle
Akteur: Hintergrunddienst, Distributor
Vorbedingung: Für den Lieferanten existiert eine `SupplierEdiConfigurations`-Konfiguration mit Format, Dokumentart und Verbindungsdaten.
Fakt: Der `EdiDownloadService` startet eine Minute nach dem Dienststart und läuft anschließend alle 30 Minuten. `SupplierEdiBL.ApplyDistriToCentron(xmlData, config, deal)` verteilt die Dateien anhand von `EdiDataType` und `ObjectKind` an die formatspezifischen Lesemethoden und löscht die Dateien nach erfolgreicher Verarbeitung. Verarbeitungszustände werden über `EDILogBL` mit den Zuständen `DownloadOK`, `DownloadError`, `DownloadTest`, `Exception`, `TestException` protokolliert.
Aussage: Das System soll Lieferantendokumente in konfigurierbaren Intervallen automatisch abrufen, formatabhängig einlesen, den zugehörigen Bestellungen zuordnen und jeden Verarbeitungsvorgang mit seinem Ergebnis protokollieren.
Ergebnis: Erfolgreich verarbeitete Dateien werden entfernt und protokolliert; fehlerhafte Dateien bleiben mit Fehlerprotokoll erhalten.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37 – Begründung: Startverzögerung und Intervall.
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs sowie die Partial-Dateien je Format – Begründung: Implementierte Verteilung und Formatverarbeitung.
- [KONTEXT] docs/reference/edi/edi-architecture.md:91-107, 237-266 – Begründung: Beschreibt Dispatch-Methode, Protokollzustände und Fehlerstrategien.
- [KONTEXT] docs/reference/edi/edi-import-rules.md – Begründung: Ergänzende Importregeln.
Prüfidee: Fehlerhafte EDI-Datei bereitstellen; nach dem nächsten Lauf muss ein Logeintrag mit `DownloadError` existieren und die Datei erhalten bleiben.
Tracelinks: StRS-014, StRS-006, SwRS-046
Konsolidierung: nein
Status: belegt
```
---
## 5. Betrieb, Wartung und Qualitätsanforderungen
```
ID: SyRS-025
Titel: Definierte Ausführungsintervalle der Hintergrunddienste
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz, Zuverlässigkeit)
Akteur: Hintergrunddienst
Vorbedingung: Der Web-Service läuft.
Fakt: Jeder Dienst deklariert `GetExecutionInterval()`. Gemessene Werte: `CallTrackingService` und `CacheUpdateService` 2 s; `ReminderService` 1 s; `SendMyDayNotificationsService` 20 s; `ObjectFulltextIndexUpdateService`, `DocumentFulltextIndexUpdateService`, `CampaignPhaseService`, `ConnectionTicketService`, `TelemetryFlushService` 1 min; `MassUpdateService`, `GfkExportService` 5 min; `CTimeConnectorService`, `EscalationsService`, `FlushAnalyticEventsService`, `TelemetryUploadService` 15 min; `ArticleImportService`, `EdiDownloadService`, `RecurringScriptService`, `SendEmailForUnreadMessagesService`, `AutoMapperMissingMappingsService` 30 min; `AutomaticPriceUpdateService`, `DataQualityService`, `RefreshIntakeService`, `PlmImportService`, `UpdateArticleAndMaterialGroupTaxRatesService`, `UpdateExpiredProvisionSchemasService`, `ValidateHelpdeskFingerprintService` 1 h; `TodoService` 6 h; `ContractCloseService`, `ContractEndeService` 1 Tag; `UpdateSpecialArticleToContractService` 30 Tage. `ObjectFulltextIndexUpdateService` und `TaskManagmentService` begrenzen ihre Laufzeit zusätzlich über `CancelAfter(15 min)` bzw. `CancelAfter(10 min)`.
Aussage: Das System soll jede Hintergrundaufgabe in einem ihrer fachlichen Dringlichkeit entsprechenden Intervall zwischen 1 Sekunde und 30 Tagen ausführen und für langlaufende Aufgaben eine harte Laufzeitgrenze setzen.
Ergebnis: Die Wiederholrate jedes Dienstes ist nachweisbar; kein Einzellauf blockiert den Dienst dauerhaft.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (33 Klassen, jeweils `GetExecutionInterval()`) – Begründung: Vollständige, im Code verankerte Intervalltabelle.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ObjectFulltextIndexUpdateService.cs:72 und TaskManagmentService.cs:78 (`CancelAfter`) – Begründung: Belegt die Laufzeitbegrenzung.
Prüfidee: Log über eine Stunde auswerten; `DataQualityService` darf genau einen und `EdiDownloadService` genau zwei Läufe aufweisen.
Tracelinks: StRS-018, SwRS-034
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-026
Titel: Zentrale Steuerung und Fehlerresilienz der Hintergrunddienste
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Zuverlässigkeit, Wartbarkeit)
Akteur: Administrator, Hintergrunddienst
Vorbedingung: Der Dienst ist gestartet.
Fakt: `ManagedBackgroundService` wartet nach dem Start zunächst 1 Minute, persistiert die Startzeit (`UpdateStartTime`) und prüft anschließend vor jedem Lauf über `BackgroundServiceBL.IsServiceEnabled(serviceName)`, ob der Dienst aktiv ist; das Ergebnis wird 60 Sekunden zwischengespeichert. Bei Ausnahmen wird `_consecutiveFailures` erhöht, `DAOFactory.Instance.TryRecoverConnectionPool(exception)` aufgerufen und die nächste Wartezeit exponentiell verlängert (`base * 2^failures`), gedeckelt auf 5 Minuten. Kann der Aktivierungszustand nicht gelesen werden, gilt der letzte bekannte Wert, ersatzweise „deaktiviert", um keine weiteren Datenbankverbindungen zu verbrauchen.
Aussage: Das System soll jeden Hintergrunddienst zentral über die Datenbank aktivierbar halten, seine Start- und letzte Laufzeit persistieren und bei wiederholten Fehlern die Ausführungsfrequenz exponentiell bis auf maximal fünf Minuten reduzieren.
Ergebnis: Ein dauerhaft fehlschlagender Dienst belastet das System nicht durch enge Wiederholungen; der Betriebszustand ist aus der Datenbank ablesbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-157 – Begründung: Enthält Aktivierungsprüfung, Cache, Backoff und Verbindungspool-Wiederherstellung vollständig.
- [KONTEXT] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:96-100, 133 (Kommentare zur Verbindungspool-Erschöpfung) – Begründung: Belegt, dass die Resilienzlogik als Reaktion auf einen realen Betriebsfehler eingeführt wurde.
Prüfidee: Datenbank während des Betriebs abschalten; die Logabstände eines Minutendienstes müssen sich schrittweise bis auf maximal fünf Minuten verlängern.
Tracelinks: StRS-018, SwRS-034
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-027
Titel: Automatische Datenbankschema-Migration beim Start
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Wartbarkeit, Übertragbarkeit)
Akteur: Administrator, System
Vorbedingung: Der Web-Service startet und besitzt eine gültige Lizenz für `ApplicationKind.Centron`.
Fakt: `ScriptEngineBL.ExecuteScripts` ermittelt alle registrierten Skriptmethoden, vergleicht sie mit den bereits ausgeführten Einträgen der Tabelle `DBUpdate` (`ScriptNumber`) und führt die fehlenden in der Reihenfolge `MethodKind`, `ApplicationVersion`, `ScriptNumber` aus, sofern `currentVersion >= method.ApplicationVersion`. Es existieren 764 Skriptklassen unter `ScriptMethods/Scripts`. Fehlgeschlagene Skripte brechen den Vorgang ab, sofern ihre Nummer nicht in `_scriptIgnoreIfErrorList` steht. `LicenseManager.LoadLicenses` prüft die Lizenz **vor** der Schemaaktualisierung mit dem ausdrücklichen Kommentar, dass eine Aktualisierung ohne Lizenz den Kunden von älteren Clients aussperren würde.
Aussage: Das System soll das Datenbankschema beim Start des Anwendungsservers automatisch auf den Stand der laufenden Programmversion bringen, jedes Skript genau einmal ausführen und die Aktualisierung ohne gültige Produktlizenz verweigern.
Ergebnis: Nach dem Start entspricht das Schema der Programmversion; `DBUpdate` enthält je ausgeführtem Skript genau einen Eintrag.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177 – Begründung: Vollständiger Migrationsalgorithmus inkl. Idempotenz über `DBUpdate` und Fehlerbehandlung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:219-236 (`LoadLicenses`) – Begründung: Durchgesetzte Lizenzvorbedingung vor der Schemaänderung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/ (764 Dateien, z. B. ScriptMethod11803.cs) – Begründung: Belegt Umfang und Form der Migrationsschritte (idempotente DDL über `ScriptHelpers.AddColumnIfNotExists` plus vollständige `ALTER VIEW`-Anweisungen).
- [KONTEXT] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:226-233 (Kommentarblock) – Begründung: Begründet die Reihenfolge Lizenzprüfung vor Migration fachlich.
- [KONTEXT] docs/guides/database/create-scripts.md – Begründung: Beschreibt den organisatorischen Prozess der Skriptnummernreservierung.
Prüfidee: Datenbank mit einem `DBUpdate`-Eintrag für Skript 11803 versehen und den Dienst starten; das Skript darf nicht erneut ausgeführt werden.
Tracelinks: StRS-004, StRS-024, SwRS-036, SwRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-028
Titel: Zweisprachige Benutzeroberfläche mit deutscher Basissprache
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Gebrauchstauglichkeit, Übertragbarkeit)
Akteur: Interner Benutzer
Vorbedingung: keine
Fakt: Lokalisierte Texte liegen als .NET-Ressourcen vor: `LocalizedStrings.resx` (deutsche Basisdatei) und `LocalizedStrings.en.resx` (englische Übersetzung). Insgesamt wurden 14 `.resx`-Dateien im Repository gefunden. Ein Teil der Meldungen ist jedoch als deutsches Stringliteral direkt im Quelltext hinterlegt (siehe StRS-019).
Aussage: Das System soll benutzersichtbare Texte über ein Ressourcensystem mit deutscher Basissprache und englischer Übersetzung bereitstellen.
Ergebnis: Bei englischer Spracheinstellung erscheinen übersetzte Texte; nicht übersetzte Schlüssel fallen auf Deutsch zurück.
Belege:
- [PRIMÄR] Verwendung von `Centron.BusinessLogic.Resources.LocalizedStrings` in AuthenticatorFactory.cs:74, BasicAuthenticator.cs:40, Authenticator.cs:74 – Begründung: Belegt die produktive Nutzung des Ressourcensystems im Anmeldepfad.
- [SEKUNDÄR] ResXManager.config.xml (Repositorywurzel) – Begründung: Werkzeugkonfiguration für die Ressourcenpflege belegt einen etablierten Übersetzungsprozess.
- [KONTEXT] docs/guides/ui/localization.md, docs/getting-started/general-structure.md:126-133 – Begründung: Beschreibt Basisdatei- und Übersetzungskonvention.
Prüfidee: Neuen Schlüssel nur in der deutschen Basisdatei anlegen und die Oberfläche auf Englisch stellen; der deutsche Text muss ohne Fehler erscheinen.
Tracelinks: StRS-019, SwRS-051
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-029
Titel: Protokollierung sicherheitsrelevanter Ereignisse
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Wartbarkeit)
Akteur: Administrator
Vorbedingung: Der Web-Service ist konfiguriert und NLog aktiv.
Fakt: Anmeldeversuche werden mit `Logger.Info("Basic authentication attempt ({RequestId}) received for user: {UserName}.")` bzw. `Logger.Warn("Basic authentication failed for user: {UserName}. Context: {AuthObject}")` protokolliert. `AuthObject.ToString()` liefert Request-ID, Anwendungsversion, Anwendungsname, Maschinenname und IP-Adresse; das Kennwort ist nicht Teil der Ausgabe. Zugriffe über Access Tokens werden über `AccessTokenLogBL` mit IP-Adresse und aufgerufener API-Methode protokolliert. Die IP-Ermittlung berücksichtigt `X-Forwarded-For` und `X-Real-IP` vor der Verbindungsadresse.
Aussage: Das System soll erfolgreiche und fehlgeschlagene Anmeldeversuche sowie Access-Token-Verwendungen mit Zeitpunkt, Benutzer, Anwendung, Gerät und Quell-IP protokollieren, ohne Geheimnisse in das Protokoll zu schreiben.
Ergebnis: Ein fehlgeschlagener Anmeldeversuch ist im Serverprotokoll mit Kontext nachvollziehbar; das Kennwort erscheint nicht.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:45,55,58,67 – Begründung: Belegt Protokollierung an allen Verzweigungen des Anmeldepfads.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:22-42 (`AuthObject.ToString`, `RemoteAddress`) – Begründung: Definiert den protokollierten Kontextumfang und schließt das Kennwort aus.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:147-172 – Begründung: Proxy-taugliche IP- und Methodenermittlung für das Zugriffsprotokoll.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:2-23 (NLog-Ziele Konsole und CSV-Datei, Regel `minLevel: Warn`) – Begründung: Belegt die konfigurierbare Protokollablage und -schwelle.
Prüfidee: Anmeldung mit falschem Kennwort durchführen; das Protokoll muss einen `Warn`-Eintrag mit Benutzername, Anwendung und IP, aber ohne Kennwort enthalten.
Tracelinks: StRS-017, SyRS-004, SyRS-009
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-030
Titel: Revisionsprotokoll für Änderungen an Rechten und Gruppen
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator
Vorbedingung: Ein Administrator ändert Rechtegruppen oder -zuordnungen.
Fakt: `AppRightsBL` schreibt für sechs Ereignisarten (`AddRightToGroup`, `RemoveRightFromGroup`, `CreateGroup`, `DeleteGroup`, `AddUserToGroup`, `RemoveUserFromGroup`, `CopyGroup`) einen `AppRightLog`-Eintrag mit `CreatedByI3D` (Mitarbeiter), `CreatedDate`, `CreatedVersion` (Assembly-Version), `Kind`, `Object` und einer deutschen Beschreibung, z. B. `Recht "{X}" an die Gruppe "{Y}" vergeben`. Die Administratorengruppe (`I3D == 6` bzw. Name „Administratoren") kann nicht gelöscht werden; für sie sind nur 34 explizit gelistete Rechte zuweisbar bzw. entziehbar.
Aussage: Das System soll jede Änderung an Rechtegruppen, Rechtezuordnungen und Gruppenmitgliedschaften revisionssicher mit Urheber, Zeitpunkt und Programmversion protokollieren und die Administratorengruppe gegen Löschung und gegen Entzug ihrer Kernrechte schützen.
Ergebnis: Rechteänderungen sind lückenlos nachvollziehbar; die Administratorengruppe bleibt handlungsfähig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-857 (`WriteBaseLog` und sechs Spezialisierungen) – Begründung: Durchgesetzte Protokollierung für alle Änderungsarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:359-360 – Begründung: Löschschutz der Administratorengruppe.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:714-759 (`GetAssignableAdminRightI3Ds`) – Begründung: Abschließende Liste der bei Administratoren änderbaren Rechte.
Prüfidee: Recht einer Gruppe zuweisen; in `AppRightLog` muss ein Eintrag mit Kind `AddRightToGroup` und dem ausführenden Mitarbeiter entstehen.
Tracelinks: StRS-002, StRS-015, SwRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-031
Titel: Feldgenaue Protokollierung fachlicher Belegänderungen
Ebene: SyRS
Typ: funktional / Compliance
Akteur: Interner Benutzer, Wirtschaftsprüfer
Vorbedingung: Ein bestehender Beleg wird geändert.
Fakt: `ReceiptBL.WriteReceiptLogs` vergleicht bei Belegen mit Kontingent 16 Einzelfelder (u. a. `ContingentKind`, `ContingentValue`, `ContingentMinimalOrderAmount`, `ContingentBalanceArticleI3D`, `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentLimitValue`) zwischen alter und neuer Version und erzeugt je Abweichung über `ReceiptLogBL` einen eigenen Logeintrag mit Alt- und Neuwert, Zeitpunkt und Benutzer. Weitere Einträge entstehen für Zahlungsstatus (`CreateSetAsPaidEntry`) und Zahlbetrag (`CreatePaidFCChangedEntry`).
Aussage: Das System soll Änderungen an abrechnungsrelevanten Belegfeldern einzeln mit Alt- und Neuwert protokollieren.
Ergebnis: Zu jeder Feldänderung existiert ein eigener, auswertbarer Protokolleintrag.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369 – Begründung: Zeigt den feldweisen Vergleich und die je Feld eigene Logmethode.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4949, 4957 (`CreateSetAsPaidEntry`, `CreatePaidFCChangedEntry`) – Begründung: Protokollierung im Zahlungspfad.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:123-143 (`AnlageLog` mit `AnlageI3D` + `AnlageArt`) – Begründung: Beschreibt die gemeinsame Logtabelle über alle Belegarten.
Prüfidee: Kontingentwert eines Vertrags ändern und speichern; im Belegprotokoll muss genau ein Eintrag mit altem und neuem Wert entstehen.
Tracelinks: StRS-015, SyRS-016
Konsolidierung: Kandidat: `ReceiptLogBL` (74 KB) enthält eine eigene Methode je Feld; im Zielsystem durch ein generisches, metadatengetriebenes Änderungsprotokoll ersetzbar.
Status: belegt
```
```
ID: SyRS-032
Titel: Verschlüsselte Ablage von Verbindungsgeheimnissen
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator
Vorbedingung: Der Web-Service besitzt eine `WebServiceConfig.xml`.
Fakt: `WebServiceConfigSerializer` liest `DatabaseConnectionString`, `ProxyPassword`, `RadiusServerSecret` und `AdditionalService.SqlPassword` über `new AESCryptoLogic().DecryptText(...)` und schreibt sie beim Speichern über `EncryptText(...)`. Ist `DatabaseConnectionString` leer, wird ersatzweise das **unverschlüsselte** Feld `DatabaseConnectionStringPlain` verwendet. Die mitgelieferte Container-Konfiguration nutzt genau diesen Klartextpfad (`Server=db; Database=Centron; User Id=SA; Password=SA!password`) und enthält zudem einen fest eingetragenen `SecretKey`, der identisch in `appsettings.Production.json` des Nexus wiederkehrt.
Aussage: Das System soll Verbindungsgeheimnisse in der Konfigurationsdatei verschlüsselt ablegen; der weiterhin unterstützte Klartextpfad ist ausschließlich für Entwicklungs- und Containerumgebungen vorgesehen und darf im Produktivbetrieb nicht verwendet werden.
Ergebnis: Produktivkonfigurationen enthalten keine Klartextgeheimnisse.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:30, 41, 56, 76, 88, 163 – Begründung: Zeigt Ver- und Entschlüsselung der vier Geheimnisfelder.
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:42-45 – Begründung: Belegt den Klartext-Fallback als bewusst implementierten Pfad.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:11-15, 33 – Begründung: Auslieferungsbeispiel nutzt Klartext-Verbindungszeichenfolge und einen mitgelieferten `SecretKey`.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:39-41 – Begründung: Derselbe `SecretKey` ist auch in der Nexus-Beispielkonfiguration hinterlegt.
Prüfidee: Produktivkonfiguration prüfen: `DatabaseConnectionStringPlain` muss leer sein und `DatabaseConnectionString` einen Chiffretext enthalten; der `SecretKey` darf nicht dem Auslieferungsbeispiel entsprechen.
Tracelinks: StRS-024, SwRS-039
Konsolidierung: nein
Status: belegt; Workaround – der Klartextpfad `DatabaseConnectionStringPlain` und die mitgelieferten Beispielgeheimnisse sind ein bekanntes Betriebsrisiko und in der Migration zu entfernen
```
```
ID: SyRS-033
Titel: Transportverschlüsselung und Zertifikatskonfiguration
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Sicherheit)
Akteur: Administrator
Vorbedingung: Der Web-Service bzw. der Nexus-Host wird betrieben.
Fakt: `WebServiceConfig` enthält `WebServiceCertificateFilePath` und `WebServiceCertificatePassword`; die Nexus-Konfiguration enthält `Host.LinuxCertificatePath` und `Host.LinuxCertificatePassword`. Die mitgelieferten Beispielkonfigurationen verwenden jedoch durchgängig `http://` (`http://localhost:1234/CentronService`, `http://localhost:8050`, `http://webservice:1234/CentronService`) und leere Zertifikatsfelder.
Aussage: Das System soll die Kommunikation zwischen Clients, Web-Service und Webanwendung über TLS absichern können; die Aktivierung erfolgt durch Hinterlegen eines Serverzertifikats in der Betriebskonfiguration.
Ergebnis: Bei hinterlegtem Zertifikat werden Endpunkte über HTTPS bereitgestellt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:35-36 – Begründung: Zertifikatsfelder sind Teil der Serverkonfiguration.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:24-28 (`LinuxCertificatePath`, `LinuxCertificatePassword`) – Begründung: Analoge Konfiguration für die Webanwendung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:3-6 und docker/compose/appsettings.Production.json:25,31 – Begründung: Belegt, dass die Auslieferungsbeispiele unverschlüsselt (`http://`) konfiguriert sind.
Prüfidee: Zertifikat hinterlegen und den Dienst neu starten; der Endpunkt muss über `https://` erreichbar sein und `http://` abgewiesen bzw. umgeleitet werden.
Tracelinks: StRS-024, SyRS-032
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – dass bei hinterlegtem Zertifikat unverschlüsselte Aufrufe abgewiesen oder umgeleitet werden, ist nicht belegt; siehe HYP-002
```
```
ID: SyRS-034
Titel: Portbasierte Trennung von Mitarbeiter- und Kundenportal
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer, Web-Account
Vorbedingung: Die Webanwendung Nexus ist konfiguriert.
Fakt: `PortAuthorization` registriert die Richtlinien `CentronAuthorization.HostPort` (Standardport 8050) und `CentronAuthorization.CustomerPortalPort`. Ist `CustomerPortalConfig.Port` nicht gesetzt, gilt die Anforderung als erfüllt und der Kundenportalport wird auf den Hostport gesetzt. Andernfalls wird `HttpContext.Connection.LocalPort` gegen den erlaubten Port geprüft und bei Abweichung eine Warnung protokolliert. Ergänzend existieren die Autorisierungsattribute `AuthorizeHostPortAttribute` und `AuthorizeCustomerPortalPortAttribute`.
Aussage: Das System soll das interne Mitarbeiterportal und das externe Kundenportal auf getrennten Netzwerkports bereitstellen können, sodass Seiten des jeweils anderen Portals über den falschen Port nicht erreichbar sind.
Ergebnis: Bei konfiguriertem Kundenportalport sind mit `AuthorizeHostPort` markierte Seiten über den Kundenportalport nicht zugänglich.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/PortAuthorization.cs:17-71 – Begründung: Vollständige, durchgesetzte Portprüfung inkl. Standardwerten.
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/Attributes/AuthorizeHostPortAttribute.cs, AuthorizeCustomerPortalPortAttribute.cs – Begründung: Anwendbare Markierung je Seite.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:33-35 (`CustomerPortal.Port: null`) – Begründung: Belegt, dass die Trennung im Auslieferungsbeispiel deaktiviert ist.
Prüfidee: `CustomerPortal.Port` auf 8060 setzen; ein Aufruf einer `AuthorizeHostPort`-Seite über Port 8060 muss abgewiesen und im Protokoll als „Port 8060 is not allowed" vermerkt werden.
Tracelinks: StRS-003, StRS-024, SwRS-041
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-035
Titel: Rechteprüfung beim Speichern eines Tickets
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Web-Account
Vorbedingung: Ein Ticket wird angelegt oder geändert.
Fakt: `HelpdeskBL.DoBeforeSave` ruft `CheckRights`, das nach Anmeldeart verzweigt. Für interne Benutzer gilt: Neuanlage erfordert `ADD_NEW_HELPDESK`; Änderung erfordert `EDIT_HELPDESK`; das Setzen des als „geschlossen" konfigurierten Status erfordert zusätzlich `CLOSE_REQUEST`; ohne `MATURITY_CHANGE` darf das Fälligkeitsdatum nicht verändert werden (geprüft über `HelpdeskRepositoryDAO.IsDueDateChanged`); mit `ASSIGN_HELPDESK_ONLY_TO_OWN_DEPARTMENTS` muss die geänderte verantwortliche Person einer eigenen Abteilung angehören. Wird ein anderer als der Abschlussstatus gesetzt, wird `ClosedAt` zurückgesetzt.
Aussage: Das System soll beim Speichern eines Tickets alle betroffenen Einzelrechte prüfen und dabei zwischen Anlegen, Ändern, Abschließen, Fälligkeitsänderung und Zuweisung unterscheiden; der Abschlusszeitpunkt soll automatisch zurückgesetzt werden, sobald das Ticket wieder geöffnet wird.
Ergebnis: Unzulässige Änderungen werden mit einer spezifischen deutschen Meldung und `RightCheckFailed` abgewiesen; `ClosedAt` ist genau dann gesetzt, wenn das Ticket im Abschlussstatus ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:310-326, 410-466 – Begründung: Vollständige, durchgesetzte Prüfkette im Speicherpfad.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:440-443 (`entity.ClosedAt = null`) – Begründung: Automatische Rücksetzung des Abschlusszeitpunkts.
- [KONTEXT] CentronRights.md:19-48 – Begründung: Beschreibt die beabsichtigte Wirkung der einzelnen Ticketrechte.
Prüfidee: Ticket ohne `MATURITY_CHANGE` mit geändertem Fälligkeitsdatum speichern; der Vorgang muss mit „Kein Recht für Fälligkeitsdatum ändern vorhanden." scheitern.
Tracelinks: StRS-008, SyRS-013, SwRS-043
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-036
Titel: Konfigurierbares Ticket-Statusmodell
Ebene: SyRS
Typ: Daten / funktional
Akteur: Administrator
Vorbedingung: keine
Fakt: Der Ticketstatus ist keine feste Aufzählung, sondern eine Stammdatenreferenz (`HelpdeskCompact.HelpdeskStateI3D` mit Anzeigetext `HelpdeskStateCaption`). Der fachlich besondere Zustand „geschlossen" wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfiguriert. Analog sind Priorität (`HelpdeskPriorityI3D`), Typ (`HelpdeskTypeI3D`) sowie Haupt- und zwei Unterkategorien als Stammdaten modelliert; im WPF-Client existieren dafür die Einstellungsmodule `Helpdesk.Settings.Status`, `.Priorities`, `.Types`, `.Categories`.
Aussage: Das System soll Ticketstatus, -prioritäten, -typen und -kategorien als vom Betreiber pflegbare Stammdaten führen und den abschließenden Status als konfigurierbare Auszeichnung eines dieser Statuswerte behandeln.
Ergebnis: Betreiber können eigene Statuswerte anlegen; die Abschlusslogik bleibt an den als „geschlossen" markierten Wert gebunden.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:17-22, 57-62 – Begründung: Status, Priorität, Typ und Kategorien sind Fremdschlüssel, keine Enumerationen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`GetClosedHelpdeskState()`) – Begründung: Der Abschlussstatus wird zur Laufzeit aus den Einstellungen gelesen.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:105,110,112,114 – Begründung: Eigene Pflegemodule für Kategorien, Prioritäten, Status und Typen.
Prüfidee: Zusätzlichen Ticketstatus anlegen und einem Ticket zuweisen; das Ticket darf dabei nicht als abgeschlossen gelten und `ClosedAt` muss leer bleiben.
Tracelinks: StRS-008, SyRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-037
Titel: Vierstufiges Mahnwesen mit Mahnstopp
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer (Debitorenbuchhaltung)
Vorbedingung: Es existieren offene Rechnungen mit überschrittenem Zahlungsziel.
Fakt: `DunningBL` kennt die Stufen `DunningLevel.None`, `Level1`, `Level2`, `Level3` und ermittelt je Stufe Anzahl und Summe des offenen Bruttobetrags als `GrossPriceComplete - PayedGrossAmount - CreditVoucherGrossAmount`. Gutschriften werden über `CreditVoucherDunning` in denselben Mahnkreis einbezogen (`customers.Union(creditVouchers)`). `UpdateDunningStopAndInfo(objectI3D, objectKind, dunningStop, dunningInfo, dunningStopBegin, dunningStopEnd, loggedInUser)` setzt einen Mahnstopp wahlweise auf Kunden- oder Rechnungsebene; Beginn wird auf Tagesanfang, Ende auf Tagesende normalisiert.
Aussage: Das System soll offene Forderungen in vier Mahnstufen führen, Gutschriften saldierend berücksichtigen und einen tagesgenau befristeten Mahnstopp je Kunde oder je Beleg zulassen.
Ergebnis: Der ausgewiesene offene Betrag ist um Zahlungen und Gutschriften bereinigt; Belege mit aktivem Mahnstopp bleiben unberücksichtigt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231 – Begründung: Vier Stufen und Berechnungsformel des offenen Betrags.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431 – Begründung: Mahnstopp auf zwei Objektebenen mit Zeitraumnormalisierung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:117,139 (`customers.Union(creditVouchers)`) – Begründung: Belegt die gemeinsame Betrachtung von Rechnungen und Gutschriften.
Prüfidee: Rechnung über 100 € mit Gutschrift über 40 € und Zahlung über 20 €; der ausgewiesene offene Betrag muss 40 € betragen.
Tracelinks: StRS-013, SwRS-033
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-038
Titel: DSGVO-konforme Anonymisierung von Kontaktdaten
Ebene: SyRS
Typ: Sicherheit / Compliance
Akteur: Administrator (Datenschutzbeauftragter)
Vorbedingung: Der Benutzer besitzt das Recht `DsgvoModule.DSGVO_DELETE_CONTACT`.
Fakt: `DataSecurityBL.DsgvoDeleteRightDeleteContacts` verarbeitet ausschließlich die Kontakttypen Ansprechpartner (Kunde und Lieferant), Kontaktmanagement-Ansprechpartner und Account-Adresskontakt über `DoDeleteContactPerson`, `DoDeleteContactManagementContactPerson`, `DoDeleteAccountAddressContact`. Die Pfade für Kunde, Lieferant, Kontaktmanagement-Kontakt und Account sind auskommentiert bzw. werfen `NotImplementedException`. Über alle Vorgänge wird ein Löschprotokoll (`deleteProtocol`) geführt und als Text zurückgegeben.
Aussage: Das System soll das Löschbegehren betroffener Personen für Ansprechpartner durch Anonymisierung und Deaktivierung erfüllen und den Vorgang protokollieren; für Kunden-, Lieferanten- und Account-Stammsätze ist diese Funktion derzeit nicht verfügbar.
Ergebnis: Anonymisierte Ansprechpartner tragen den Text „DSGVO: Auf Anfrage gelöscht. (Durchgeführt von … am … um … Uhr)"; ein Protokoll dokumentiert den Vorgang.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:787-855 – Begründung: Zeigt die tatsächlich implementierten und die auskommentierten Löschpfade.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:856-1030 (`NotImplementedException` und auskommentierte SQL-Anweisungen) – Begründung: Belegt den unfertigen Zustand für Stammsätze.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 – Begründung: Definiert den Anonymisierungstext inklusive Nachweis des Ausführenden.
Prüfidee: DSGVO-Löschung für einen Ansprechpartner ausführen und das zurückgegebene Protokoll prüfen; es muss den anonymisierten Datensatz benennen.
Tracelinks: StRS-016, SwRS-047
Konsolidierung: nein
Status: belegt; Workaround – unvollständige Implementierung, in der Validierung mit hoher Priorität zu klären
```
```
ID: SyRS-039
Titel: Vermeidung redundanter Belegdokumente
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz)
Akteur: System
Vorbedingung: Ein Belegreport wird als PDF erzeugt und abgelegt.
Fakt: `ReceiptBL.AddReportPdf` ruft vor der Ablage `DocumentsBL.GetIdenticalDocumentInDirectory(directoryI3D, name, reportPdf, receipt.Version)` und gibt bei Treffer die bestehende Dokument-I3D zurück, ohne ein neues Dokument anzulegen. Der Kommentar verweist auf Ticket 160276 und begründet dies damit, dass ein erneuter Export derselben Belegversion ein bytegleiches PDF erzeugt.
Aussage: Das System soll bei wiederholtem Export derselben Belegversion mit demselben Report kein zusätzliches Dokument speichern, sondern das bestehende referenzieren.
Ergebnis: Der Dokumentenspeicher wächst nicht durch wiederholte Exporte derselben Belegversion.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3483 – Begründung: Durchgesetzte Dublettenprüfung vor der Ablage.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3476 (Ticketreferenz 160276) – Begründung: Weist die Regel als nachträgliche Korrektur eines Betriebsproblems aus.
Prüfidee: Denselben Beleg fünfmal exportieren; im Belegordner darf nur ein Dokument entstehen.
Tracelinks: StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-040
Titel: Verteilte Betriebstopologie
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit, Wartbarkeit)
Akteur: Administrator
Vorbedingung: keine
Fakt: Die `compose.yaml` definiert vier Dienste: `db` (MSSQL-Image), `webservice` (Start über `/app/Centron.Host.Console`, Containerport 1234, veröffentlicht als 4321, Konfiguration über eingebundene `WebServiceConfig.xml`, `restart: on-failure`, Umgebungsvariable `HARDWARE_ID`), `smtp` (Mailcatcher, Ports 1025/1080) und `nexus` (Start über `/app/CentronNexus.Host`, Port 8050, Konfiguration über `appsettings.Production.json`, abhängig vom Web-Service). Nexus erreicht den Web-Service über `http://webservice:1234/CentronService`. Zusätzlich existieren Windows-Installationspakete (WiX) für Client und Web-Service.
Aussage: Das System soll aus einer Datenbank, einem Anwendungsserver, einer Webanwendung und optionalen Zusatzdiensten bestehen, die netzwerkseitig getrennt betrieben und über konfigurierbare Endpunkte verbunden werden.
Ergebnis: Die Komponenten sind unabhängig deploybar; die Webanwendung greift ausschließlich über den Anwendungsserver auf die Datenbank zu.
Belege:
- [PRIMÄR] docker/compose/compose.yaml:1-54 – Begründung: Vollständige Topologiedefinition mit Abhängigkeiten und Ports.
- [PRIMÄR] docker/compose/appsettings.Production.json:30-32 (`CentronWebService.Url`) – Begründung: Belegt, dass Nexus den Web-Service als einzige Datenquelle adressiert.
- [PRIMÄR] deployment/centron/CentronSetupProject/Product.wxs, deployment/centron/WebServiceSetupProject/Product.wxs – Begründung: Getrennte Installationspakete für Client und Server.
- [SEKUNDÄR] docker/c-entron-webservice/Dockerfile, docker/c-entron-api/Dockerfile – Begründung: Containerisierung der Serverkomponenten.
Prüfidee: Web-Service-Container stoppen; Nexus muss weiterlaufen, aber jede fachliche Aktion mit einem Verbindungsfehler quittieren.
Tracelinks: StRS-024, SwRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-041
Titel: Umschaltbare Datenzugriffsart des Fachclients
Ebene: SyRS
Typ: Schnittstelle / nicht-funktional (ISO 25010: Übertragbarkeit)
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Client ist mit einer Verbindung vom Typ `SqlServer` oder `CentronWebServices` konfiguriert.
Fakt: Jedes Clientmodul deklariert in seinem `AppModuleController` über `SupportsConnectionTypes` die unterstützten Verbindungsarten (`CentronConnectionType.CentronWebServices`, `CentronConnectionType.SqlServer`). Der `ClassContainer` löst zur Laufzeit die Schnittstelle `I{Modul}Logic` gegen `BL{Modul}Logic` (direkter Datenbankzugriff) oder `WS{Modul}Logic` (Web-Service-Aufruf) auf. Beide Implementierungen liefern `Task<Result<T>>`.
Aussage: Das System soll denselben Fachclient wahlweise mit direktem Datenbankzugriff oder über den Anwendungsserver betreiben können, wobei jedes Modul angibt, welche Betriebsarten es unterstützt.
Ergebnis: Ein Modul, das eine Verbindungsart nicht unterstützt, wird in dieser Betriebsart nicht angeboten.
Belege:
- [KONTEXT] docs/getting-started/general-structure.md:15-113 – Begründung: Beschreibt Muster, Namenskonvention und die Pflicht zur Doppelimplementierung ausführlich; die Codebeispiele stammen aus `IAccountContractsLogic`.
- [PRIMÄR] src/centron/Centron.WPF.UI/Services/ (688 Dateien mit `BL*Logic`/`WS*Logic`-Paaren) – Begründung: Die Doppelimplementierung ist in der Codebasis breit umgesetzt.
- [PRIMÄR] src/webservice/c-entron.misc.ConnectionManager/ – Begründung: Eigene Komponente zur Verbindungsverwaltung.
Prüfidee: Client mit Verbindungsart `CentronWebServices` starten; ein Modul, das nur `SqlServer` deklariert, darf nicht im Menü erscheinen.
Tracelinks: StRS-024, SwRS-001, SwRS-002
Konsolidierung: Kandidat: SwRS-002 – jede Fachfunktion existiert doppelt (BL- und WS-Variante); im Zielsystem als reine Web-/SaaS-Architektur auf einen Pfad zu reduzieren.
Status: belegt; Teilaussage [HYPOTHESE] – die Vollständigkeit der Doppelimplementierung über alle Module ist nicht verifiziert; siehe HYP-006
```
```
ID: SyRS-042
Titel: Stapelverarbeitung großer Datenmengen
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz)
Akteur: System
Vorbedingung: Eine Operation betrifft eine große Menge von Datensätzen.
Fakt: Massenoperationen zerlegen Schlüssellisten vor der Datenbankabfrage in Blöcke zu 2 000 Elementen: `TaxBL.UpdateArticleVATs` verarbeitet `articleI3DsWithOldTaxRate.Batch(2000)`; `AutomaticFacturaBL.SearchBillingContracts` verwendet an fünf Stellen `.Batch(2000)` vor benannten Abfragen. Ergänzend existieren Cache-Mechanismen (`Session.Advanced.Cache.GetOrAdd`) und ein `CacheUpdateService` mit 2-Sekunden-Takt und 1-Minuten-Optimierungsintervall.
Aussage: Das System soll Datenbankabfragen mit Listenparametern in Blöcken von höchstens 2 000 Schlüsseln ausführen, um Grenzen des Datenbanksystems einzuhalten und die Antwortzeit zu begrenzen.
Ergebnis: Auch Operationen über zehntausende Datensätze werden ohne Abfragefehler ausgeführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:117 (`Batch(2000)`) – Begründung: Konkrete, durchgesetzte Blockgröße.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:861, 890, 898, 910, 924 – Begründung: Dieselbe Blockgröße an fünf weiteren Stellen belegt die Konvention.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/CacheUpdateService.cs:30,46 – Begründung: Ergänzende Cache-Strategie zur Lastreduktion.
Prüfidee: Steuersatzumstellung für 5 000 Artikel auslösen; die Operation muss ohne Parameterlimit-Fehler durchlaufen und in drei Blöcken erfolgen.
Tracelinks: StRS-007, SwRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-043
Titel: Erhebung und Übermittlung von Betriebstelemetrie
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Wartbarkeit) / Datenschutz
Akteur: Lizenzgeber (NEXOWARE), Administrator
Vorbedingung: Die Telemetriedienste sind aktiviert.
Fakt: Der Web-Service enthält eine Telemetriekomponente mit `TelemetryAggregator`, `HttpTelemetryUploadClient`, `DatabaseGuidProvider` und `HardwareIdProvider`. `TelemetryFlushService` schreibt im Minutentakt, `TelemetryUploadService` überträgt alle 15 Minuten. Der `ApiCallTelemetryInterceptor` und der `McpToolUsageTelemetryInterceptor` erfassen API-Aufrufe. `CentronAnalytics` und `FlushAnalyticEventsService` (15 min) erfassen Nutzungsereignisse.
Aussage: Das System soll Nutzungs- und Betriebsdaten erheben, lokal aggregieren und in regelmäßigen Abständen an den Hersteller übertragen; die übertragenen Daten sind über Datenbank- und Hardwarekennung dem Betreiber zuordenbar.
Ergebnis: Aggregierte API-Nutzungsdaten werden alle 15 Minuten übertragen.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/Telemetry/ (`TelemetryAggregator`, `HttpTelemetryUploadClient`, `DatabaseGuidProvider`, `HardwareIdProvider`) – Begründung: Vollständige Telemetriekette inkl. Identifikationsmerkmalen.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryFlushService.cs:21 und TelemetryUploadService.cs:33 – Begründung: Konkrete Aggregations- und Übertragungsintervalle.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/ApiCallTelemetryInterceptor.cs – Begründung: Erfassung erfolgt querschnittlich bei jedem API-Aufruf.
Prüfidee: Netzwerkverkehr des Web-Service beobachten; innerhalb von 15 Minuten muss genau eine Telemetrieübertragung erfolgen.
Tracelinks: StRS-018, StRS-024
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – welche Inhalte konkret übertragen werden und ob ein Opt-out besteht, ist nicht belegt; siehe HYP-007
```
@@ -0,0 +1,185 @@
# Traceability-Matrix
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Bezug:** `StRS.md`, `SyRS.md`, `SwRS.md`
Die Matrix stellt Forward-Traceability (StRS → SyRS → SwRS) und Backward-Traceability
(SwRS → SyRS → StRS) her. Die Spalte *Artefaktbeleg* nennt das jeweils zentrale, in den
Anforderungen als `PRIMÄR` klassifizierte Artefakt der Kette. Ein `—` bedeutet, dass auf der
betreffenden Ebene keine eigenständige Anforderung abgeleitet werden konnte; diese Lücken sind
im `Analysebericht.md`, Abschnitt „Bekannte Lücken", aufgeführt.
Prüfergebnis des maschinellen Konsistenzchecks (siehe `Analysebericht.md`):
**119 Anforderungen, keine doppelten IDs, keine Tracelinks auf nicht existierende IDs, jede
Anforderung mit mindestens einem `PRIMÄR`-Beleg.**
---
## 1. Konsolidierte Matrix
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg |
|---|---|---|---|
| StRS-001 Mandanten-/Filialfähigkeit | SyRS-015 Belegnummernvergabe | SwRS-010 NumberGroup-Entität | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152` |
| StRS-001 | SyRS-015 | SwRS-011 Nummernreservierung | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:62-92` |
| StRS-001 | SyRS-012 Einschränkende Rechte | SwRS-015 Zentrale Belegrechteprüfung | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10295` |
| StRS-002 Rollenbasierte Zugriffssteuerung | SyRS-011 Rechteauflösung über Gruppen | SwRS-016 Rechte-Caching | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:644-664` |
| StRS-002 | SyRS-011 | SwRS-017 Sichtrus/Sichmemb | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:97-101, 653-656` |
| StRS-002 | SyRS-011 | SwRS-018 UserRightsConst | `src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:10-16` |
| StRS-002 | SyRS-012 | SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295` |
| StRS-002 | SyRS-030 Rechte-Audit | SwRS-019 Schutz der Standardrechtestruktur | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:348-374, 762-857` |
| StRS-002 | SyRS-011 | SwRS-040 Modulregistrierung | `src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs` |
| StRS-003 Kundenselbstbedienung | SyRS-013 Web-Account-Rechtemodell | SwRS-041 Nexus-Autorisierungsattribute | `src/nexus/CentronNexus/Shared/Authorization/Attributes/` |
| StRS-003 | SyRS-034 Portbasierte Portaltrennung | SwRS-041 | `src/nexus/CentronNexus/Shared/Authorization/PortAuthorization.cs:17-71` |
| StRS-003 | SyRS-003 Anmeldeverfahren | SwRS-042 Nexus-Anmeldung mit Rückfall | `src/nexus/CentronNexus/Shared/Auth/AuthService.cs:49-71` |
| StRS-003 | SyRS-010 Methodenbeschränkung | SwRS-027 Interceptorkette | `…/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:29-48` |
| StRS-004 Lizenzabhängiger Funktionsumfang | SyRS-007 Lizenz-/Kontingentprüfung | SwRS-020 ApplicationKind | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| StRS-004 | SyRS-007 | SwRS-021 LicenseGuids | `src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs` |
| StRS-004 | SyRS-008 Anwendungsrechteprüfung | SwRS-020 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:68-86` |
| StRS-004 | SyRS-009 Access Tokens | SwRS-025 Token-Lizenzkontingent | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:436-451` |
| StRS-004 | SyRS-027 Schemamigration | SwRS-036 ScriptEngineBL | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:219-236` |
| StRS-005 Verkaufsbelegfluss | SyRS-014 Belegzustandsmodell | SwRS-012 ReceiptState | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28` |
| StRS-005 | SyRS-016 Belegversionierung | SwRS-013 Datums-/Versionsvalidierung | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578` |
| StRS-005 | SyRS-016 | SwRS-004 ReceiptBase | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72` |
| StRS-005 | SyRS-018 Rechteprüfung beim Speichern | SwRS-009 SpecificLogics | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3600-3634` |
| StRS-005 | SyRS-016 | SwRS-014 Belegvorlagen | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:65` |
| StRS-005 | SyRS-020 Steuersatzermittlung | SwRS-028 Steuersatzkette | `src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237` |
| StRS-006 Beschaffungsprozess | SyRS-015 | SwRS-010 | `src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:40-55, 106-117` |
| StRS-006 | SyRS-019 Lagerbuchung | SwRS-030 Mengendifferenzbuchung | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:212-231` |
| StRS-006 | SyRS-024 EDI-Import | SwRS-046 EDI-Partial-Classes | `src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.*.cs` |
| StRS-007 Vertragsgeschäft | SyRS-022 Vertragsselektion | SwRS-032 Abrechnungslauf und -protokoll | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845, 2101-2118` |
| StRS-007 | SyRS-042 Stapelverarbeitung | SwRS-028 | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:861, 890, 898, 910, 924` |
| StRS-008 Helpdesk | SyRS-035 Ticket-Rechteprüfung | SwRS-043 Feldlängenbegrenzung | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:328-349, 410-466` |
| StRS-008 | SyRS-036 Konfigurierbares Statusmodell | SwRS-044 Kurzbeschreibungspräfix | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:351-393, 433` |
| StRS-009 Servicezeiterfassung | SyRS-035 | SwRS-043 | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90` |
| StRS-010 Lagerbestandsführung | SyRS-019 | SwRS-030 | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:171-236` |
| StRS-010 | SyRS-019 | SwRS-031 IsBooked-Konsistenzprüfung | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:207-210` |
| StRS-011 Elektronische Rechnung | SyRS-023 Formatableitung | SwRS-045 ZUGFeRD-Parametrisierung | `…/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289` |
| StRS-012 Buchhaltungsübergabe | SyRS-023 | SwRS-045 | `…/DataExchange/BookKeeping/BookKeepingExportBL.cs:832, 1437, 1560` |
| StRS-013 Mahnwesen | SyRS-037 Mahnstufen und Mahnstopp | SwRS-033 Mahnstufenauswertung | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231, 392-431` |
| StRS-014 EDI-Anbindung | SyRS-024 | SwRS-046 | `src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37` |
| StRS-015 Revisionssicherheit | SyRS-016 | SwRS-007 Versionstabellen | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3595-3634` |
| StRS-015 | SyRS-031 Feldgenaues Belegprotokoll | SwRS-013 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369` |
| StRS-015 | SyRS-017 Nebenläufigkeitsschutz | SwRS-004 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4939-4940` |
| StRS-016 DSGVO-Betroffenenrechte | SyRS-038 Anonymisierung | SwRS-047 DSGVO-Löschlogik | `…/Administration/DataSecurity/DataSecurityBL.cs:26-27, 787-855` |
| StRS-017 Identitätsanbindung / 2FA | SyRS-003 | SwRS-023 Authenticator-Strategiemuster | `…/Administration/Logins/Auth/AuthenticatorFactory.cs:54-147` |
| StRS-017 | SyRS-004 Kennwortprüfung | SwRS-024 Hashverfahren | `…/Administration/Logins/Auth/BasicAuthenticator.cs:46-50` |
| StRS-017 | SyRS-005 Kontodeaktivierung | SwRS-023 | `…/Administration/Logins/Auth/Authenticator.cs:157-218` |
| StRS-017 | SyRS-006 Zwei-Faktor-Authentifizierung | SwRS-023 | `…/Administration/Logins/TwoFactor/` |
| StRS-018 Hintergrundverarbeitung | SyRS-025 Ausführungsintervalle | SwRS-034 ManagedBackgroundService | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94` |
| StRS-018 | SyRS-026 Steuerung und Resilienz | SwRS-034 | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:101-157` |
| StRS-018 | SyRS-025 | SwRS-035 Datenqualitätsaufgaben | `…/AspNetCore/HostedServices/DataQualityService.cs:28-71, 183` |
| StRS-018 | SyRS-023 / SyRS-036 | SwRS-038 Einstellungssysteme | `src/backend/Centron.BL/Administration/Settings/AppSettingsConst.cs` |
| StRS-018 | SyRS-043 Telemetrie | — | `src/webservice/Centron.Host/AspNetCore/Telemetry/` |
| StRS-019 Deutsch als Primärsprache | SyRS-028 Zweisprachigkeit | SwRS-051 ResX-Lokalisierung | `LocalizedStrings.resx` / `LocalizedStrings.en.resx`, `ResXManager.config.xml` |
| StRS-020 Online-Banking | SyRS-014 | SwRS-033 | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
| StRS-020 | SyRS-037 | SwRS-033 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4920-4958` |
| StRS-021 Belegdruck und PDF-Ablage | SyRS-039 Dublettenvermeidung | — | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3483` |
| StRS-022 Provisionsermittlung | SyRS-018 | — | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs` |
| StRS-023 RMA-Abwicklung | SyRS-014 | SwRS-012 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180` |
| StRS-024 Verteilte Betriebstopologie | SyRS-040 Topologie | SwRS-048 Technologiebasis | `docker/compose/compose.yaml:1-54` |
| StRS-024 | SyRS-041 Umschaltbarer Datenzugriff | SwRS-001 Schichtenarchitektur | `Centron.sln`, `src/centron/Centron.WPF.UI/Services/` |
| StRS-024 | SyRS-041 | SwRS-002 Doppelimplementierung BL/WS | `src/centron/Centron.WPF.UI/Services/` (688 Dateien) |
| StRS-024 | SyRS-041 | SwRS-003 Result-Fehlermodell | `src/backend/Centron.Interfaces/BL/` |
| StRS-024 | SyRS-027 | SwRS-006 Dualschema Tabellen/Sichten | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs` |
| StRS-024 | SyRS-027 | SwRS-036 Skriptbasierte Migration | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177` |
| StRS-024 | SyRS-027 | SwRS-037 Idempotente Schemaänderungen | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs:14-20` |
| StRS-024 | SyRS-027 | SwRS-049 Bau- und Versionierungsvorgaben | `Directory.Build.props:6-43`, `version.json` |
| StRS-024 | SyRS-027 | SwRS-050 CI-/CD-Pipelines | `.github/workflows/`, `azure/` |
| StRS-024 | SyRS-032 Verschlüsselte Geheimnisse | SwRS-039 Konfigurationsserialisierung | `…/WebServiceConfiguration/WebServiceConfigSerializer.cs:30,41,56,88,163` |
| StRS-024 | SyRS-033 Transportverschlüsselung | SwRS-039 | `…/WebServiceConfigSerializer.cs:35-36`, `docker/compose/appsettings.Production.json:24-28` |
| StRS-024 | SyRS-016 | SwRS-008 Legacy-Persistenzpfad | `src/backend/Centron.DAO/Repositories/`, `…/Entities/DbEntities/` |
| StRS-025 Preisfindung | SyRS-021 Vorrangfolge | SwRS-029 Konditionsarten | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266` |
| StRS-002 / StRS-004 | SyRS-001 Ticketauthentifizierung | SwRS-022 Ticketentität | `…/Administration/Logins/Auth/Authenticator.cs:94-155`, `TicketBL.cs:61-94` |
| StRS-002 | SyRS-001 | SwRS-026 ASP.NET-Core-Ticketschema | `src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:38-144` |
| StRS-002 | SyRS-001 | SwRS-027 Interceptorkette | `…/WcfBridge/Interception/Interceptors/` (8 Klassen) |
| StRS-002 | SyRS-002 Ticketlebensdauer | SwRS-022 | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:26-28, 113-164` |
| StRS-002 | SyRS-029 Sicherheitsprotokollierung | SwRS-024 | `…/Auth/BasicAuthenticator.cs:45,55,58,67`, `…/Auth/Authenticator.cs:22-42` |
| StRS-005 | SyRS-014 | SwRS-005 Objekttypschlüssel | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:20-264` |
---
## 2. Rückwärtsverfolgung: SwRS → SyRS → StRS (Kurzform)
| SwRS-ID | Titel | → SyRS | → StRS |
|---|---|---|---|
| SwRS-001 | Schichtenarchitektur | SyRS-041 | StRS-024 |
| SwRS-002 | Doppelimplementierung BL/WS | SyRS-041 | StRS-024 |
| SwRS-003 | Result-Fehlermodell | SyRS-041, SyRS-018 | StRS-024, StRS-002 |
| SwRS-004 | ReceiptBase-Hierarchie | SyRS-014, SyRS-016 | StRS-005 |
| SwRS-005 | CentronObjectKindNumeric | SyRS-031 | StRS-005 |
| SwRS-006 | Dualschema Tabellen/Sichten | SyRS-027 | StRS-024 |
| SwRS-007 | Versionstabellen | SyRS-016 | StRS-015 |
| SwRS-008 | Legacy-Persistenzpfad | SyRS-016 | StRS-024 |
| SwRS-009 | SpecificLogics-Delegation | SyRS-015, SyRS-018 | StRS-005 |
| SwRS-010 | NumberGroup-Entität | SyRS-015 | StRS-001 |
| SwRS-011 | Nummernreservierung | SyRS-015 | StRS-001 |
| SwRS-012 | ReceiptState | SyRS-014 | StRS-005 |
| SwRS-013 | Datums-/Versionsvalidierung | SyRS-016 | StRS-005, StRS-015 |
| SwRS-014 | Belegvorlagen | SyRS-015 | StRS-005 |
| SwRS-015 | Zentrale Belegrechteprüfung | SyRS-012, SyRS-018 | StRS-002 |
| SwRS-016 | Rechte-Caching | SyRS-011 | StRS-002 |
| SwRS-017 | Sichtrus/Sichmemb | SyRS-011 | StRS-002 |
| SwRS-018 | UserRightsConst | SyRS-008, SyRS-011 | StRS-002 |
| SwRS-019 | Schutz der Standardrechtestruktur | SyRS-030 | StRS-002 |
| SwRS-020 | ApplicationKind | SyRS-007, SyRS-008 | StRS-004 |
| SwRS-021 | LicenseGuids | SyRS-007 | StRS-004 |
| SwRS-022 | Ticketentität | SyRS-001, SyRS-002, SyRS-007 | StRS-002, StRS-004 |
| SwRS-023 | Authenticator-Strategiemuster | SyRS-003 | StRS-017 |
| SwRS-024 | Hashverfahren | SyRS-004, SyRS-009, SyRS-032 | StRS-017 |
| SwRS-025 | Token-Lizenzkontingent | SyRS-009 | StRS-004 |
| SwRS-026 | ASP.NET-Core-Ticketschema | SyRS-001, SyRS-009 | StRS-002 |
| SwRS-027 | Interceptorkette | SyRS-001, SyRS-010, SyRS-043 | StRS-002, StRS-003 |
| SwRS-028 | Steuersatzkette | SyRS-020, SyRS-042 | StRS-005, StRS-011 |
| SwRS-029 | Konditionsarten | SyRS-021 | StRS-025 |
| SwRS-030 | Mengendifferenzbuchung | SyRS-019 | StRS-010 |
| SwRS-031 | IsBooked-Konsistenzprüfung | SyRS-019 | StRS-010 |
| SwRS-032 | Vertragsabrechnungslauf | SyRS-022 | StRS-007 |
| SwRS-033 | Mahnstufenauswertung | SyRS-037 | StRS-013 |
| SwRS-034 | ManagedBackgroundService | SyRS-025, SyRS-026 | StRS-018 |
| SwRS-035 | Datenqualitätsaufgaben | SyRS-025, SyRS-026 | StRS-018 |
| SwRS-036 | ScriptEngineBL | SyRS-027 | StRS-024, StRS-004 |
| SwRS-037 | ScriptHelpers | SyRS-027 | StRS-024 |
| SwRS-038 | Einstellungssysteme | SyRS-023, SyRS-036 | StRS-018 |
| SwRS-039 | Konfigurationsserialisierung | SyRS-032, SyRS-033 | StRS-024 |
| SwRS-040 | Modulregistrierung | SyRS-011 | StRS-002, StRS-004 |
| SwRS-041 | Nexus-Autorisierungsattribute | SyRS-013, SyRS-034 | StRS-003 |
| SwRS-042 | Nexus-Anmeldung | SyRS-003 | StRS-003 |
| SwRS-043 | Ticket-Feldlängen | SyRS-035 | StRS-008 |
| SwRS-044 | Ticket-Präfix | SyRS-035, SyRS-036 | StRS-008 |
| SwRS-045 | ZUGFeRD-Parametrisierung | SyRS-023 | StRS-011 |
| SwRS-046 | EDI-Partial-Classes | SyRS-024 | StRS-014 |
| SwRS-047 | DSGVO-Löschlogik | SyRS-038 | StRS-016 |
| SwRS-048 | Technologiebasis | SyRS-040 | StRS-024 |
| SwRS-049 | Bau- und Versionierungsvorgaben | SyRS-027 | StRS-024 |
| SwRS-050 | CI-/CD-Pipelines | SyRS-027 | StRS-024 |
| SwRS-051 | ResX-Lokalisierung | SyRS-028 | StRS-019 |
---
## 3. Konsolidierungskandidaten (modulübergreifende Redundanz)
Die folgende Übersicht fasst alle in den Anforderungen im Feld `Konsolidierung` vermerkten
Kandidaten zusammen. Sie ist die zentrale Arbeitsliste für die Zusammenführung fachlich gleicher
Funktionen im Zielsystem.
| # | Redundanz | Betroffene Anforderungen | Empfehlung für das Zielsystem |
|---|---|---|---|
| K-01 | Zwei getrennte Rechtemodelle (Mitarbeiter über `Sichtrus`/`Sichmemb`, Web-Accounts über `WebAccountsRights`) mit disjunktem Nummernraum | StRS-002, StRS-003, SyRS-011, SyRS-013 | Ein einheitliches Rollen-/Berechtigungsmodell mit Mandanten-, Filial- und Kundenkontext |
| K-02 | Muster „Basisrecht + ONLY_OWN + ONLY_OWN_BRANCH" für 7 Belegarten, Tickets, Kalender, CRM-Projekte und Projektverwaltung dupliziert | SyRS-012 | Generisches, deklaratives Sichtbarkeitskonzept (Datenbereichsfilter) statt Einzelrechte |
| K-03 | Doppelimplementierung jeder Fachfunktion als `BL*Logic` und `WS*Logic` (ca. 688 Clientdateien) | SyRS-041, SwRS-002 | Bei Web-/SaaS-Zielarchitektur entfällt der Direktzugriff; ein Pfad genügt |
| K-04 | Zwei Persistenzpfade für Belege (NHibernate-Entität + `SaveReceipt*Repository` auf Alttabellen) | SwRS-006, SwRS-008 | Ein Persistenzmodell auf einem bereinigten Schema |
| K-05 | Zweischichtiges Datenbankschema (deutsche Alttabellen + englische Sichten) | SwRS-006 | Ein Schema mit durchgängig englischer Benennung |
| K-06 | Drei Hashverfahren für Geheimnisse (SHA-1 ohne Salt, SHA-256, gesalzener Hash) | SyRS-004, SwRS-024 | Ein modernes, gesalzenes Verfahren (PBKDF2/Argon2) für alle Geheimnisse |
| K-07 | Zwei Ticketprüfpfade (WCF-Bridge-Interceptor und ASP.NET-Core-Handler) | SyRS-001, SwRS-026, SwRS-027 | Ein Authentifizierungs-Middleware-Pfad |
| K-08 | Drei Konditionsstrukturen für Sonderpreise (Vertrag, Kunde, Staffel) | StRS-025, SyRS-021, SwRS-029 | Einheitliches Konditionsmodell mit Gültigkeitszeitraum, Preisbasis und Vorrangregel |
| K-09 | Drei Einstellungsschalter für dasselbe E-Rechnungsprofil (`ActiveZugferdInterface`, `IsZugferdXRechnungActive`, `IsXRechung2Active`) | SyRS-023 | Ein Schalter mit Profilliste |
| K-10 | Zwei Anwendungseinstellungssysteme (`Stammdat` und `ApplicationSettings`) | SwRS-038 | Ein typisiertes Einstellungssystem mit Metadaten |
| K-11 | Optimistische Nebenläufigkeitsprüfung an sieben Stellen kopiert | SyRS-017 | Zentrale Kapselung in der Persistenzschicht |
| K-12 | Änderungsprotokoll mit je einer Logmethode pro Feld (`ReceiptLogBL`, 74 KB) | SyRS-031 | Metadatengetriebenes, generisches Änderungsprotokoll |
| K-13 | Rechte-IDs dupliziert in `ApplicationKind.cs`, `WebAccountRightsConst.cs` und `GetAssignableAdminRightI3Ds()` | SyRS-008, SwRS-018 | Eine Quelle für alle Rechtekennungen |
| K-14 | Zwei Textquellen (ResX-Ressourcen und deutsche Quelltextliterale) | StRS-019, SwRS-051 | Ausschließlich Ressourcen, keine Literale |
| K-15 | Zwei Skriptformen für Datenbankmigrationen (C#-Klassen, XML-Sammlungen) | SwRS-036 | Ein Migrationsformat |
| K-16 | Zwei CI-Systeme (GitHub Actions, Azure DevOps) mit teilweise gleichen Aufgaben | SwRS-050 | Ein CI-/CD-System |
| K-17 | Zwei Anzeigetextquellen für `ReceiptState` (`[Description]` und `GetReceiptStateString`), beide nicht lokalisiert | SwRS-012 | Ein lokalisierter Anzeigetext je Zustand |
| K-18 | Sechs strukturgleiche EDI-Leseimplementierungen je Distributor | SwRS-046 | Plug-in-Schnittstelle mit einheitlichem Zwischenformat |
| K-19 | Kunden- und Lieferantenbelege teilen `ReceiptBase`, unterscheiden sich aber in Persistenz und Nummernkreisen | StRS-005, StRS-006 | Einheitliches Belegmodell mit Rollenunterscheidung (Debitor/Kreditor) |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 18 (Lauf L)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:43+02:00
- **Endzeit:** 2026-08-25T20:44:48+02:00
- **Dauer gesamt:** 00:45:05 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:45:04 (`duration_ms`) — API: 00:43:56
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-6bfe`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 256
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/21 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 170 |
| Output-Tokens | 237.695 (davon 24.179 Thinking-Tokens) |
| Cache-Write-Tokens | 522.004 |
| Cache-Read-Tokens | 21.995.319 |
| Agent-Turns | 195 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 170 | 4.192 | 4.362 |
| Output-Tokens | 237.695 | 21 | 237.716 |
| Cache-Write-Tokens | 522.004 | 0 | 522.004 |
| Cache-Read-Tokens | 21.995.319 | 0 | 21.995.319 |
| Tokens gesamt | 22.755.188 | 4.213 | **22.759.401** |
**Tokens gesamt: 22.759.401** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `1054e7e0-425a-4f2c-b765-6da095439081`
- **Permission-Denials:** **1** – 1 x `PowerShell` - `New-Item -ItemType Directory` auf das eigene, bereits vorhandene `Ergebnisse\`-Verzeichnis; von `PowerShell(New-Item:*)` geblockt. Folgenlos, alle 7 Artefakte entstanden.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 59.919 B | 25 Anforderungen |
| `SyRS.md` | 93.621 B | 43 Anforderungen |
| `SwRS.md` | 106.930 B | 51 Anforderungen |
| `Traceability.md` | 18.443 B | 77 Datenzeilen |
| `Hypothesen.md` | 16.868 B | 22 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 21.640 B | Domänenbegriffe |
| `Analysebericht.md` | 24.107 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **119 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,0 % |
| SyRS | 43 | 36,1 % |
| SwRS | 51 | 42,9 % |
| **Gesamt** | **119** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 28 | 23,5 % |
| Sicherheit | 22 | 18,5 % |
| Daten | 15 | 12,6 % |
| Schnittstelle | 6 | 5,0 % |
| Architektur | 6 | 5,0 % |
| Sicherheit / Compliance | 3 | 2,5 % |
| nicht-funktional (ISO 25010: Performanz-Effizienz) | 3 | 2,5 % |
| Sicherheit / nicht-funktional (ISO 25010: Sicherheit) | 2 | 1,7 % |
| Schnittstelle / Sicherheit | 2 | 1,7 % |
| Daten / funktional | 2 | 1,7 % |
| (27 weitere) | 30 | 25,2 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 378 |
| davon `PRIMÄR` | 271 (71,7 %) |
| davon `SEKUNDÄR` | 37 (9,8 %) |
| davon `KONTEXT` | 70 (18,5 %) |
| Belege je Anforderung (Median) | 3 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 119 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 112 | 94,1 % |
| als `HYPOTHESE` gekennzeichnet | 7 | 5,9 % |
| als Workaround vermerkt | 29 | 24,4 % |
| Konsolidierungskandidaten | 30 | 25,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (54 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 119 von 119 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(256 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2636391,"num_turns":195,"stop_reason":"end_turn","session_id":"1054e7e0-425a-4f2c-b765-6da095439081","total_cost_usd":22.1652215,"usage":{"input_tokens":170,"cache_creation_input_tokens":522004,"cache_read_input_tokens":21995319,"output_tokens":237695,"output_tokens_details":{"thinking_tokens":24179},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":522004,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1283,"cache_read_input_tokens":542364,"cache_creation_input_tokens":576,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":576},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":21,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0042970000000000005,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":170,"outputTokens":237695,"cacheReadInputTokens":21995319,"cacheCreationInputTokens":522004,"webSearchRequests":0,"costUSD":22.1609245,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[{"tool_name":"PowerShell","tool_use_id":"toolu_01YW7YLKyVN5QigJvq36TXar","tool_input":{"command":"$p=\"c:\\DEV\\MasterArbeit\\Versuche\\Versuch_01\\01_Lauf_2026-08-25_195915_opus5_solo_v3.6.0-6bfe\\Ergebnisse\"; if(-not (Test-Path $p)){ New-Item -ItemType Directory -Force $p | Out-Null }; Get-ChildItem $p | Format-Table -AutoSize","description":"Ensure output directory exists"}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Die Codebasis ist unverändert (`git status` leer), alle sieben Ergebnisdateien liegen im vorgegebenen Ausgabeverzeichnis.\n\n## Ergebnis\n\n**119 Anforderungen** auf drei Ebenen, jede mit mindestens einem `PRIMÄR`-Beleg:\n\n| Datei | Inhalt | Umfang |\n|---|---|---|\n| `StRS.md` | 25 Stakeholder-Anforderungen + Akteurstabelle | 58 KB |\n| `SyRS.md` | 43 Systemanforderungen (Auth/Lizenz, Rechte, Belege, Schnittstellen, Betrieb) | 91 KB |\n| `SwRS.md` | 51 Softwareanforderungen (Architektur, Datenmodell, Fachlogik, Betriebskomponenten) | 104 KB |\n| `Traceability.md` | Vorwärts-/Rückwärtsmatrix + 19 verdichtete Konsolidierungskandidaten | 18 KB |\n| `Hypothesen.md` | 12 Hypothesen mit fehlender Information und offener Frage | 16 KB |\n| `Glossar.md` | 7 Begriffsgruppen mit technischer Entsprechung und Beleg | 21 KB |\n| `Analysebericht.md` | Komponentenübersicht, Analysetiefe, Konsistenzcheck, Selbstbewertung | 23 KB |\n\n**Konsistenzcheck (maschinell ausgeführt):** keine doppelten IDs, keine Anforderung ohne Beleg, keine Tracelinks auf nicht existierende IDs, jede SwRS referenziert eine SyRS, jede SyRS eine StRS. Belegverteilung: 271 `PRIMÄR` / 37 `SEKUNDÄR` / 70 `KONTEXT` (71,7 % primär).\n\n**Zwei Punkte, die für die Validierung hervorstechen:**\n\n1. Die Entwicklerdokumentation unter `docs/` habe ich durchgängig als `KONTEXT` klassifiziert, nicht als `PRIMÄR` — sie widerspricht dem Code nachweisbar beim Belegzustandsmodell (Doku: vier Zustände „Draft/Released/Processed/Cancelled\", Code: drei Zustände `Active/Completed/Canceled`). Dokumentiert als W-01 und HYP-009.\n\n2. 29 Anforderungen tragen `Status: … Workaround`. Die sieben kritischsten sind im Analysebericht priorisiert, darunter ungesalzenes SHA-1 für Benutzerkennwörter (mit `// TODO the password should be salted!!!` im Quelltext), die unvollständige DSGVO-Löschung (`NotImplementedException` für Kunden-, Lieferanten- und Account-Stammsätze) und der doppelte Belegpersistenzpfad.\n\n**Zur Einordnung der Abdeckung:** Die architektur- und sicherheitsprägenden Mechanismen sind weitgehend vollständig erfasst; die fachliche Breite schätze ich auf etwa ein Drittel. Nicht analysiert blieben u. a. Statistik/Auswertung, Passwortmanager, Telefonie, KI-Modul und die Fremd-API-Anbindungen — vollständig aufgelistet in Abschnitt 2 des Analyseberichts. Der wirkungsvollste Nachschlag wäre ein Datenbankschema-Abzug: er lag nicht vor und ist die Hauptursache der verbliebenen `KONTEXT`-Belege im Datenmodellbereich.","ttft_ms":1763,"ttft_stream_ms":1017,"time_to_request_ms":46,"type":"result","duration_ms":2703563,"uuid":"3f298d5f-7cdd-426f-9822-eb84d7f82386","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,0 % |
| SyRS | 43 | 36,1 % |
| SwRS | 51 | 42,9 % |
| **Gesamt** | **119** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 28 | 23,5 % |
| Sicherheit | 22 | 18,5 % |
| Daten | 15 | 12,6 % |
| Schnittstelle | 6 | 5,0 % |
| Architektur | 6 | 5,0 % |
| Sicherheit / Compliance | 3 | 2,5 % |
| nicht-funktional (ISO 25010: Performanz-Effizienz) | 3 | 2,5 % |
| Sicherheit / nicht-funktional (ISO 25010: Sicherheit) | 2 | 1,7 % |
| Schnittstelle / Sicherheit | 2 | 1,7 % |
| Daten / funktional | 2 | 1,7 % |
| (27 weitere) | 30 | 25,2 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 378 |
| davon `PRIMÄR` | 271 (71,7 %) |
| davon `SEKUNDÄR` | 37 (9,8 %) |
| davon `KONTEXT` | 70 (18,5 %) |
| Belege je Anforderung (Median) | 3 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 119 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 112 | 94,1 % |
| als `HYPOTHESE` gekennzeichnet | 7 | 5,9 % |
| als Workaround vermerkt | 29 | 24,4 % |
| Konsolidierungskandidaten | 30 | 25,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (54 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 119 von 119 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195915_opus5_solo_v3.6.0-6bfe\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:44:48.7401722+02:00
@@ -0,0 +1 @@
2026-08-25T19:59:43.6861284+02:00
@@ -0,0 +1,281 @@
# Analysebericht
**System:** NEXOWARE c-entron ERP
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse ohne Ausführung
**Analysebasis:** `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48`, Branch `main`
**Iteration:** V1 Baseline (Prompt-only), Lauf 01 · **Werkzeugkonfiguration:** Claude Code ohne Agentendateien, ohne MCP-Server
**Erstellt:** 2026-08-25
---
## 1. Umfang des Untersuchungsgegenstands
Die Codebasis wurde vollständig erhoben und quantifiziert:
| Kennzahl | Wert |
|---|---|
| Projekte in `Centron.sln` | 44 |
| C#-Quelldateien (ohne `bin`/`obj`) | 14 782 (67,4 MB) |
| XAML-Dateien | 1 233 (15,8 MB) |
| Razor-Dateien (Blazor) | 491 (4,2 MB) |
| CSS-Dateien | 264 · JS 40 · XML 28 · JSON 16 · YAML/YML 26 · resx 14 |
| Markdown-Dokumentation | 50 Dateien (`docs/`: 44 Sachdateien) |
| Commits in der Historie | 52 135 |
| NHibernate-Entitätsdateien | 1 179 |
| NHibernate-Zuordnungsdateien | 983 |
| Datenbank-Migrationsskripte | 764 |
| Anwendungseinstellungen (`ApplicationSettingID`) | 492 |
| Anwendungseinstellungen (`AppSettingsConst`, Legacy) | 728 |
| Legacy-REST-Methoden | 2 599 (davon 2 374 mit `[Authenticate]`) |
| Moderne REST-Endpunkte | 160 in 42 Controllern |
| Registrierte Client-Module | 84 in 15 Modulgruppen |
| Hintergrunddienste | 35 |
| Benutzerrechte (`UserRightsConst`) | über 900 Konstanten |
| Lizenz-GUIDs | 159 |
| Anmeldefähige Anwendungsarten | 44 |
| Objektarten (`CentronObjectKindNumeric`) | 205 |
| Testprojekte | 12 (378 C#-Dateien) |
**Keine SQL-Dateien im Repository.** Das Datenbankschema existiert ausschließlich als C#-Migrationsskripte (`ScriptMethod*.cs`) und FluentNHibernate-Zuordnungen. Eine vollständige Schemarekonstruktion war in dieser Iteration nicht Gegenstand der Analyse.
**Zielplattform:** .NET 10 (`global.json`: SDK 10.0.100). `Centron.BL` mit Multi-Targeting `net10.0;net10.0-windows`; Web-Service und Datenzugriff plattformneutral (`net10.0`); nur der WPF-Client ist Windows-gebunden. Produktversion laut `version.json`: `2.0.2611-alpha`.
---
## 2. Modul- und Komponentenübersicht
### 2.1 Ausführungseinheiten
| Einheit | Projekt(e) | Rolle |
|---|---|---|
| Windows-Fachclient | `Centron.WPF.UI`, `Centron.WPF.UI.Extension` | Vollständige ERP-Bedienoberfläche (WPF/DevExpress) |
| Web-Service | `Centron.Host` + `Centron.Host.Console` / `.WindowsService` | Zentrale Server-API, 35 Hintergrunddienste, Lizenz- und Sitzungsverwaltung |
| Moderne API | `Centron.Controllers` | Versionierte ASP.NET-Core-REST-Schnittstelle |
| Webportal | `CentronNexus`, `CentronNexus.Host` | Blazor-Server (ServiceBoard, WebCart, WebOffer, C-Sign) |
| Outlook-Erweiterung | `CentronNexus.OutlookAddIn` | Office-Add-In für CRM-, Ticket- und Belegzugriff |
| Konfigurationswerkzeug | `c-entron.misc.ConnectionManager` | Erzeugung der `WebServiceConfig.xml` (nur Windows) |
| Gemeinsame Schichten | `Centron.BL`, `Centron.DAO`, `Centron.Entities`, `Centron.Interfaces`, `Centron.Common`, `Centron.Gateway`, `Centron.Core`, `Centron.Controls` | Fachlogik, Persistenz, Datenmodell, Verträge, Hilfsfunktionen, Format-Gateways, gemeinsame Steuerelemente |
| Externe Integrationen | `src/apis/` (7 Projekte), `Centron.Api.docuFORM` | ITscope, Icecat, COP, EGIS, FinAPI, GLS, Shipcloud, docuFORM |
### 2.2 Fachliche Modulgruppen des Clients (15 Gruppen, 84 Module)
Abrechnung · Administration · Adressen/CRM · Automatisierung · Buchhaltung/Finanzen · Controlling/Analytics · Einkauf · Helpdesk · Hilfe · Logistik · MyCentron · Passwort Manager (abgekündigt) · Produktion · Stammdaten · Verträge
### 2.3 Fachlogik nach Größe (`Centron.BL`)
| Bereich | Dateien | Größte Einzelkomponente |
|---|---|---|
| Administration | 959 | `ScriptMethodsCollection.cs` (714 KB), `AppSettingsGroupBL.cs` (153 KB) |
| WebServices (DTO-Wandlung) | 464 | `ReceiptWebServiceBL.cs` (239 KB) |
| Sales | 248 | `ReceiptBL.cs` (609 KB), `ReceiptItemBL.cs` (225 KB) |
| Warehousing | 40 | `ArticleBL.cs` (206 KB), `ArticleImportBL.cs` (139 KB) |
| Accounts | 29 | `AccountWebServiceBL.cs` (121 KB) |
| EDI | 27 | `SupplierEdiBL.cs` (118 KB) |
| ReportEngine | 26 | `ReportDataBL.cs` (92 KB) |
| ArtificialIntelligence | 25 | – |
| DataExchange | 23 | `InvoiceZugferdBL.cs` (120 KB), `BookKeepingExportBL.cs` (81 KB) |
| Statistics | 16 | `ContractEvaluationBL.cs` (87 KB) |
---
## 3. Analysetiefe je Bereich
Die Analysetiefe wurde risikobasiert priorisiert: Sicherheits-, Abrechnungs- und Berechtigungslogik zuerst, danach Belegverarbeitung und Datenmodell, zuletzt Betriebs- und Bauartefakte.
**Legende:** ● vollständig gelesen · ◐ gezielt gelesen (Schlüsselstellen im Detail, Rest über Struktur/Signaturen) · ○ nur strukturell erfasst (Dateibaum, Klassennamen, Größen) · – nicht analysiert
| Bereich | Tiefe | Was konkret gelesen wurde | Anforderungen |
|---|---|---|---|
| **Authentifizierung / Sitzung** | ● | `Authenticator.cs`, `AuthenticatorFactory.cs`, `BasicAuthenticator.cs`, `WebAccountAuthenticator.cs`, `TicketBL.cs`, `TwoFactorAuthBL.cs`, `JwtAuthController.cs` — vollständig | SyRS-001…008, SwRS-025, SwRS-026 |
| **Autorisierung / Rechtemodell** | ● | `AppRightsBL.cs` (vollständig), `UserRightsConst.cs` (Hierarchieteil vollständig, Konstantenblock stichprobenhaft), `AuthorizeUserRightAttribute.cs`, `Authorization/README.md`, `CentronRights.md` | StRS-002, SyRS-009…014, SwRS-002, SwRS-003, SwRS-040 |
| **Lizenzierung** | ● | `LicenseManager.cs` (vollständig), `ApplicationKind.cs` (vollständig), `LicenseGuids.cs` (Kopfteil + Auszählung) | StRS-004, SyRS-007, SyRS-008, SwRS-005 |
| **Belegverarbeitung (Kern)** | ◐ | `ReceiptBL.cs`: ca. 1 100 der 12 500 Zeilen im Detail (Speicherpfad 3517–3868, Versionierung 3063–3175, Nummernvergabe 7257–7285, Limitprüfung 8636–8712, Mindestpreis 9036–9124, Abschluss 9753–9803, Rechteprüfungen 10194–10312); Rest über Methodensignaturen | StRS-005, SyRS-016…024, SwRS-006…010 |
| **Belegzustand / Objektarten** | ● | `ReceiptState.cs`, `ReceiptBase.cs`, `CentronObjectKindNumeric.cs` — vollständig | SyRS-016, SwRS-004, SwRS-006 |
| **Lager / Artikelbuchung** | ◐ | `ReceiptArticleBookingBL.cs` (Buchungs- und Rechtelogik im Detail), `ArticleBL.cs` (Rechteermittlung), Struktur `Warehousing/` | StRS-008, SyRS-025, SwRS-013 |
| **Ticket / Helpdesk** | ◐ | `HelpdeskBL.cs` (Rechte-, Längen- und Präfixlogik im Detail), Struktur `Sales/Support/` (53 Klassen) | StRS-007, SyRS-026, SyRS-027, SwRS-011, SwRS-012 |
| **Vertrag / Abrechnung** | ◐ | Abrechnungs-Aufzählungen vollständig; `AutomaticFacturaWebServiceBL.cs` (RMM-Prüfung, `CreateInvoiceToContractComplete` Kopfteil); `contracts-backend.md` vollständig | StRS-006, StRS-021, SyRS-029, SwRS-014 |
| **E-Rechnung (ZUGFeRD/XRechnung)** | ◐ | `InvoiceZugferdBL.cs` Zeilen 52–242 im Detail; Generatorteil strukturell | StRS-012, SyRS-030, SwRS-015 |
| **DSGVO / Datenschutz** | ◐ | `DataSecurityBL.cs`: Rechteprüfungen und zwei Anonymisierungsroutinen im Detail; SQL-Referenzblöcke gesichtet | StRS-013, SyRS-028, SwRS-016 |
| **Änderungsprotokollierung** | ● | `ChangeTrackingEventListener.cs` — vollständig | SyRS-046, SwRS-017 |
| **Hintergrunddienste** | ◐ | `ManagedBackgroundService.cs` vollständig; alle 35 Dienstklassen nach Name und Intervall erfasst; `DataQualityService.md` vollständig | StRS-025, SyRS-035, SyRS-045, SwRS-029 |
| **Schnittstellen (REST)** | ◐ | `AuthenticateAttribute.cs` vollständig; alle `ICentronRestService*.cs` maschinell ausgezählt (Attribute, Verben, Lücken); `ICentronRestService.Receipts.cs` als Muster gelesen; 42 Controller nach Namen und Verbanzahl erfasst | SyRS-010, SyRS-011, SyRS-031, SwRS-030 |
| **Nummernvergabe** | ● | `NumberGroupBL.cs` — vollständig | SyRS-018, SwRS-032 |
| **Konfiguration / Einstellungen** | ◐ | `WebServiceConfig.xml`, `appsettings.json`, `Directory.Build.props`, `global.json`, `version.json`, `compose.yaml` vollständig; `ApplicationSettingID.cs` Kopfteil + Auszählung; `settings-management.md` vollständig | StRS-024, SyRS-049, SwRS-028, SwRS-034 |
| **Betrieb / Deployment** | ◐ | Docker-Verzeichnis vollständig; WiX-Projekte strukturell; `web-service-on-linux.md` vollständig | StRS-019, SyRS-039…041, SwRS-023, SwRS-033 |
| **Datenmodell / Persistenz** | ○ | Verzeichnisstruktur und Dateizahl erfasst; Konventionen aus `database-conventions.md` und `script-rules.md`; `AssetHeadDAO` **nicht** gelesen | SwRS-018, SwRS-039, SwRS-007, SwRS-008 |
| **Lokalisierung** | ○ | Alle `.resx` nach Pfad und Größe erfasst; Inhalte nicht gelesen | StRS-018, SyRS-048, SwRS-022 |
| **Client-Oberfläche (WPF)** | ○ | Verzeichnisstruktur, `ModuleRegistration.cs` (Kopfteil + alle 84 Registrierungen ausgelesen); keine einzelne View/ViewModel im Detail | StRS-001, SyRS-015, SwRS-036 |
| **Webportal (Blazor)** | ○ | Verzeichnisstruktur und Dateizahlen; `appsettings.json` vollständig; `DocumentSigning`-Komponenten nach Namen; keine `.razor`-Datei im Detail | StRS-011, StRS-023, SyRS-037, SyRS-038, SwRS-027 |
| **EDI** | ○ | Partialklassenstruktur, Gateway-Bibliotheken, `edi-architecture.md` vollständig; **keine** Parserimplementierung gelesen | StRS-009 |
| **Externe Integrationen (`src/apis/`)** | ○ | Projekt- und Ordnerstruktur; Anbieterklassen der Artikelsuche nach Namen | StRS-020, SyRS-034, SwRS-024 |
| **Statistik / Reporting** | ○ | Verzeichnisstruktur und Dateigrößen; Rechteblock vollständig | StRS-017, SwRS-021 |
| **Provision** | ○ | Entitätsnamen, Komponentennamen, Rechteblock | StRS-016, SwRS-020 |
| **Finanzen / Mahnwesen / Buchhaltungsexport** | ○ | `DunningLevel.cs` vollständig; `DunningBL.cs`, `DunningRunBL.cs`, `BookKeepingExportBL.cs` nur nach Name und Größe | StRS-010, SyRS-024 |
| **Telemetrie** | ○ | Dienst- und Entitätsnamen; **Inhalt nicht gelesen** | SwRS-037 (HYPOTHESE) |
| **Künstliche Intelligenz (`Centron.BL/ArtificialIntelligence`, 25 Dateien)** | – | nicht analysiert | – |
| **Produktion / PLM** | – | nur als Modulname erfasst | – |
| **Passwort-Manager** | – | nur als Modul- und Rechtename erfasst | – |
| **TAPI / Telefonie** | – | nur als Modul-, Dienst- und Rechtename erfasst | – |
| **MyDay / TaskManager / Kalender** | – | nur als Modul- und Dienstname erfasst | – |
| **Skriptmethoden (764 Migrationsskripte)** | – | nur ausgezählt; kein einzelnes Skript gelesen | – |
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde maschinell über die drei Spezifikationsdateien ausgeführt (Auswertung der Felder `ID`, `Belege`, `Prüfidee`, `Status`, `Tracelinks`).
| Prüfung | Ergebnis |
|---|---|
| **Anzahl Anforderungen** | 114 (25 StRS, 49 SyRS, 40 SwRS) |
| **Doppelte oder mehrfach vergebene IDs** | **keine** |
| **Anforderungen ohne Beleg** | **keine** (0 von 114) |
| **Anforderungen ohne `PRIMÄR`-Beleg** | **keine** (0 von 114) — die Belegpflicht der risikobasierten Priorisierung (Sicherheit, Abrechnung, Berechtigungen) ist damit für alle Anforderungen erfüllt |
| **Anforderungen ohne Prüfidee** | **keine** |
| **Anforderungen ohne Statusfeld** | **keine** |
| **Tracelinks auf nicht existierende IDs** | **keine** |
| **StRS ohne SyRS-Verweis** | keine |
| **SyRS ohne StRS-Verweis** | keine |
| **SyRS ohne SwRS-Verweis** | keine |
| **SwRS ohne SyRS-Verweis** | keine |
| **SwRS ohne direkten StRS-Verweis** | keine |
| **Belege gesamt** | 421 (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`) |
| **Durchschnitt `PRIMÄR`-Belege je Anforderung** | 2,75 |
| **Als `[HYPOTHESE]` gekennzeichnet** | 6 |
| **Mit Zusatz `Workaround` im Feld `Status`** | 18 |
### 4.1 Im Verlauf gefundene und behobene Inkonsistenzen
Beim ersten Konsistenzdurchlauf traten sieben fehlerhafte Tracelinks auf, die bereits korrigiert sind und hier zur Nachvollziehbarkeit dokumentiert werden:
1. **StRS-001 bis StRS-025:** Die Tracelinks waren zunächst gegen eine vorläufige SyRS-Nummerierung gesetzt und zeigten nach der endgültigen Nummerierung auf inhaltlich unpassende Anforderungen. Alle 25 wurden gegen die tatsächlichen Inhalte geprüft und neu gesetzt.
2. **Fehlende SyRS-Ebene für vier Themen:** Änderungsprotokollierung, Rechteänderungsprotokoll, Sprachvorgabe und Anwendungseinstellungen hatten keine Entsprechung auf Systemebene; die StRS verwies deshalb direkt auf die SwRS-Ebene. Ergänzt als **SyRS-046, SyRS-047, SyRS-048, SyRS-049**.
3. **SyRS-034 → SwRS-012:** verwies auf „Konfigurierbare Ticketzustände" statt auf die Integrationskomponenten. Korrigiert auf SwRS-015, SwRS-024.
4. **SyRS-037 → SwRS-014** und **SyRS-038 → SwRS-014:** Portal-Grenzwerte verwiesen auf die Vertragsabrechnung. Korrigiert auf SwRS-034 bzw. SwRS-038.
5. **SyRS-042 → SwRS-032:** E-Mail-Schutz verwies auf die SQL-Verkettung. Korrigiert auf SwRS-035 (Build-Vorgaben, DEBUG-/RELEASE-Unterscheidung).
6. **SyRS-044:** Titel nannte „acht Testprojekte", der Beleg 12. Titel korrigiert.
7. **SwRS-017, SwRS-022, SwRS-028:** verwiesen auf SyRS-036 (Protokollierung) statt auf die jeweils zutreffende neue SyRS-Anforderung. Korrigiert.
### 4.2 Verbleibende Einschränkung
Die Verweise sind **vollständig, aber nicht durchgängig spiegelbildlich**: Ein Verweis ist teils nur in der einen, teils nur in der anderen Anforderung notiert. `Traceability.md` löst dies auf, indem beide Matrizen die Vereinigung aus Vor- und Rückwärtsverweisen bilden. Die vollständige Spiegelung in den Quelldokumenten ist für eine Folge-Iteration vorgemerkt.
---
## 5. Selbstbewertung
### 5.1 Vollständig analysierte Bereiche
Für diese Bereiche liegt eine Anforderungsableitung vor, die den gesamten Entscheidungsraum des Codes abbildet — nicht nur Stichproben:
- **Authentifizierung und Sitzungsverwaltung.** Alle sechs Authentifikator-Implementierungen, die Verfahrenswahl, die Sperrprüfung, die Ticketlebensdauer und die Zwei-Faktor-Logik sind vollständig erschlossen. Der Nachweis der ungesalzenen SHA-1-Kennwortspeicherung ist eindeutig.
- **Rechtemodell.** `AppRightsBL` vollständig; das Datenmodell (`Sichrech`/`Sichgrup`/`Sichtrus`/`Sichmemb`/`Sichbenu`), die Hierarchieauflösung, der Administratorschutz, die Standardrechtestruktur und das Rechteänderungsprotokoll sind belegt.
- **Lizenzierung.** Lizenzprüfung, Anwendungsarten, Ticketzählung, Modulsichtbarkeit und der Zusammenhang „keine Datenbankaktualisierung ohne Lizenz" sind vollständig nachgezeichnet.
- **Belegzustandsmodell und Objektartsystematik.** Abschließend belegt.
- **Nummernvergabe.** Vollständig, einschließlich Nebenläufigkeitssicherung und Lückenprüfung.
- **Änderungsprotokollierung.** Vollständig, einschließlich der beiden Abbruchbedingungen.
- **Betriebsmodell der Hintergrunddienste.** Vollständig; die Basisklasse regelt alle 35 Dienste einheitlich.
### 5.2 Stichprobenhaft analysierte Bereiche
- **`ReceiptBL.cs`** — die zentrale Belegkomponente mit 609 KB. Gelesen wurden rund 9 % der Zeilen, gezielt an den Stellen mit Geschäftsregelcharakter. Die 46 Einzelprüfungen der Speichersequenz sind namentlich und in ihrer Reihenfolge erfasst, aber nur sieben davon inhaltlich analysiert (`CheckIfCustomerLimitIsReached`, `CheckArticleMinPrices`, `CheckExternalInvoiceNumberAlreadyUsed`, `CheckForDuplicatePurchaseOrderNumber`, `TryAutomaticallyCloseReceipt`, `CanUser*`-Familie, `UpdateReceiptNumber`). **Das ist die größte inhaltliche Lücke dieser Iteration.**
- **Helpdesk, Vertragsabrechnung, DSGVO, E-Rechnung, Lagerbuchung.** Jeweils die geschäftsregelrelevanten Methoden gelesen, der übrige Code strukturell erfasst.
- **Schnittstellen.** Vollständig ausgezählt und in ihrer Systematik belegt, aber nur eine Partialdatei inhaltlich gelesen. Aussagen über einzelne Endpunkte sind nur für die namentlich genannten belastbar.
### 5.3 Nicht analysierte Bereiche
Diese Bereiche sind im Anforderungssatz **nicht** oder nur als Modulname vertreten:
| Bereich | Umfang | Begründung der Zurückstellung |
|---|---|---|
| Künstliche Intelligenz | 25 BL-Klassen, 5 Rechte, eigener Controller, `ArtificialIntelligenceChatsController` | Neuer Funktionsbereich ohne erkennbare Kopplung an die Kernprozesse; niedrige Migrationspriorität |
| Produktion / PLM | 2 BL-Klassen, `ProductionOrderManagement` im Portal, `PlmImportService` | Kleiner Umfang, klar abgegrenzt |
| Passwort-Manager | 10 Entitäten, 6 BL-Klassen, eigener Rechteblock, eigene Lizenz | Eigenständiges Zusatzprodukt |
| TAPI / Telefonie | `TapiServer`-Anwendungsart, `TapiClientHub`, `Telephony`-Steuerelemente | Technische Integration ohne ERP-Kernbezug |
| MyDay / TaskManager / Kalender / ToDo | 11 + 20 + Kalender-BL (`ScheduleBL.cs`, 128 KB) | Umfangreich, aber ohne Berührung der risikopriorisierten Themen |
| Mailings / SocialMedia / VideoPortal / DocuBoard | je 1–13 Klassen | Randbereiche |
| SelfCare (`SelfCareWebserviceBL.cs`, 137 KB) | 10 BL-Klassen, eigene Objektarten | Umfangreich; im Zusammenhang mit den anonymen REST-Endpunkten sicherheitsrelevant |
| 764 Migrationsskripte | – | Für Anforderungen nicht auswertbar; relevant nur für eine Schemarekonstruktion |
| Report-Engine (Berichtsdefinitionen) | 26 BL-Klassen, `Centron.Interfaces/CentronReportEngine` | Darstellungsschicht |
### 5.4 Stellen mit dünner Belegdecke
22 der 114 Anforderungen (19 %) haben mindestens so viele `SEKUNDÄR`- und `KONTEXT`-Belege wie `PRIMÄR`-Belege. Neun Anforderungen stützen sich auf genau einen `PRIMÄR`-Beleg. Die kritischsten Fälle:
| Anforderung | Belegverhältnis | Bewertung |
|---|---|---|
| **SwRS-007** (Zweigleisige Belegpersistenz) | 1 PRIMÄR / 3 KONTEXT | Die Aussage über den Schreibpfad (`SaveReceipt*Repository`, `SynchronizeReceiptData`) stützt sich überwiegend auf `receipts-backend-architecture.md`. Der `PRIMÄR`-Beleg belegt nur die **Existenz** der temporären Legacy-Entitäten, nicht ihren Einsatz im Speicherpfad. **Diese Anforderung beschreibt die aufwendigste Struktur der gesamten Belegverarbeitung und ist am schwächsten belegt.** |
| **SwRS-008** (Versionstabellen) | 1 PRIMÄR / 2 KONTEXT | Die Kopiermechanik (`AssetHeadDAO.SaveAssetVersion`, `DoGetFieldList()`) wurde nicht gelesen. |
| **SyRS-044** (Testabdeckung) | 1 PRIMÄR / 3 KONTEXT | Der Umfang ist ausgezählt; die Aussage zur Teststrategie stammt aus der Dokumentation. |
| **SyRS-039** (DB-Strukturaktualisierung) | 2 PRIMÄR / 2 KONTEXT | Die Idempotenzforderung ist eine Projektregel; kein einzelnes Skript wurde auf Einhaltung geprüft. |
| **SwRS-018** (Datenmodellkonventionen) | 2 PRIMÄR / 2 KONTEXT | Konventionen stammen aus der Dokumentation; keine Stichprobe an tatsächlichen Tabellen. |
| **SwRS-036** (MVVM-Struktur) | 2 PRIMÄR / 2 KONTEXT | Struktur belegt, Einhaltung nicht geprüft (keine View im Detail gelesen). |
| **SyRS-032** (Dualer Client-Datenzugriff) | 1 PRIMÄR / 2 KONTEXT | Das Muster ist über den Dateibaum belegt; die Vollständigkeit („jedes Modul implementiert beide") ist Projektregel, nicht nachgewiesen. |
| **SyRS-042** (E-Mail-Schutz) | Kernaussage nur KONTEXT | Als `[HYPOTHESE]` gekennzeichnet; `DeveloperSecurity.cs` nicht auffindbar. |
**Bewertung:** Die dünnen Stellen liegen systematisch dort, wo die Projektdokumentation umfangreich ist und deshalb als Einstieg diente — Persistenzarchitektur, Datenmodellkonventionen, Teststrategie, Architekturmuster. Das ist ein methodisches Muster dieser Iteration, kein Zufall: Wo `docs/` eine fertige Beschreibung liefert, sinkt der Anreiz zur Codeverifikation. Für die Validierung bedeutet das, dass gerade die architekturbeschreibenden Anforderungen (SwRS-001, SwRS-007, SwRS-008, SwRS-018, SwRS-036) am ehesten von der Realität abweichen können.
### 5.5 Belastbarkeit für eine Neuimplementierung
| Bereich | Belastbarkeit | Begründung |
|---|---|---|
| Authentifizierung, Autorisierung, Lizenzierung | **hoch** | Vollständig gelesen, dichte `PRIMÄR`-Belege, Entscheidungsräume abschließend erfasst |
| Belegzustand, Versionierung, Nummernvergabe | **hoch** | Regeln vollständig, mit Fehlermeldungstexten und Randfällen |
| Kreditlimit, Mindestpreis, negative Lagerbuchung, Mahnstufensperre | **hoch** | Vollständige Regeln inkl. Ausnahmen und Übersteuerungspfaden |
| DSGVO, Änderungsprotokollierung | **hoch** | Verarbeitungsschritte feldgenau belegt |
| Belegvalidierung insgesamt | **mittel** | Alle 46 Prüfungen benannt, 7 inhaltlich erschlossen |
| Vertragsabrechnung, E-Rechnung, Ticketverarbeitung | **mittel** | Kernregeln belegt, Detailverhalten offen |
| Persistenzarchitektur | **mittel bis niedrig** | Struktur bekannt, Mechanik nur dokumentationsgestützt |
| EDI, externe Integrationen, Statistik, Provision, Finanzen | **niedrig** | Nur Struktur- und Rechteebene; keine Verarbeitungsregeln |
| KI, Produktion, Passwort-Manager, Telefonie, MyDay, SelfCare | **nicht abgedeckt** | Für diese Bereiche liegt keine Anforderung vor |
---
## 6. Erkenntnisse mit unmittelbarem Handlungsbedarf
Unabhängig von der Neuimplementierung ergaben sich drei Befunde am **laufenden System**:
1. **221 Legacy-REST-Methoden ohne Authentifizierungsmarker** (SyRS-011, Hypothese H-01). Darunter schreibende Operationen wie `DeleteLogo`, `SaveCustomerSpecialArticle` und `DeleteContractExternalArticleImportHead`. Ob ein impliziter Schutz greift, ist ohne Laufzeitprüfung nicht entscheidbar. **Höchste Priorität.**
2. **Ungesalzene SHA-1-Kennwortspeicherung** für Mitarbeiter- **und** Portalkonten (SwRS-026, Hypothese H-02). Der Ist-Zustand ist durch `PRIMÄR`-Belege eindeutig; der Quelltext enthält den Kommentar `// TODO the password should be salted!!!`. Das Kennwort ist zudem Teil der Datenbankabfrage, ein Vergleich in konstanter Zeit findet nicht statt.
3. **Bekannte NuGet-Schwachstellen brechen den Build bewusst nicht ab** (SyRS-043). `Directory.Build.props` nimmt `NU1901`–`NU1904` ausdrücklich von `TreatWarningsAsErrors` aus. Zusätzlich ist `EnableUnsafeBinaryFormatterSerialization` aktiviert.
Ergänzend sind zwei bereits in der Projektdokumentation benannte offene Punkte bestätigt: das Zertifikatskennwort steht im Klartext in `WebServiceConfig.xml`, und die Skriptnummernvergabe erfolgt über eine repository-externe Excel-Datei.
---
## 7. Nachschlag für eine Folge-Iteration
Priorisiert nach erwartetem Erkenntnisgewinn je Aufwand:
### Rang 1 — Belegvalidierung vervollständigen
Die 39 noch nicht inhaltlich analysierten `Check*`-Methoden in `ReceiptBL.cs` (Zeilen 3703–3755) lesen. Jede von ihnen ist eine Geschäftsregel mit Pflichtfeld- oder Plausibilitätscharakter (Kostenstelle, Kostenträger, Umsatzsteuer-Identifikationsnummer, Leistungszeitraum, Bestellnummer, Projektnummer, Lizenznehmeranschrift, WEEE, Klassifizierung, Leasing/Service, Mandat, Prioritätsänderung, Zusatztext, E-Mail-Pflicht). **Erwarteter Zuwachs: 25–35 Anforderungen** im am dichtesten belegten Bereich.
### Rang 2 — Persistenzmechanik verifizieren
`AssetHeadDAO.SaveAssetVersion`, ein `SaveReceipt*Repository` und die zugehörigen `SynchronizeReceiptData`/`SynchronizeReceiptItemData` lesen. Damit werden SwRS-007 und SwRS-008 von dokumentations- auf codegestützt gehoben. **Hebt die Belastbarkeit der Persistenzarchitektur von „mittel bis niedrig" auf „hoch".**
### Rang 3 — Sicherheitsbefunde klären
Interception-Bridge lesen (`Centron.Host.AspNetCore.WcfBridge.Interception`), um H-01 zu entscheiden. Gezielt nach `DeveloperSecurity` bzw. `AllowSendingEmailToExternalAddresses` suchen, um H-04 zu entscheiden. `TelemetryUploadService.cs` und die 12 Telemetrieentitäten lesen, um H-05 zu entscheiden.
### Rang 4 — Nicht abgedeckte Fachbereiche erschließen
In dieser Reihenfolge: **SelfCare** (137 KB, sicherheitsrelevant wegen der anonymen Endpunkte), **Kalender/MyDay/TaskManager** (`ScheduleBL.cs`, 128 KB), **Finanzen** (`DunningBL.cs`, `BookKeepingExportBL.cs`), **EDI-Parser** (mindestens ein Distributorformat exemplarisch), **Provision** (`ReceiptProvisionBL.cs`), **Statistik** (`ContractEvaluationBL.cs`).
### Rang 5 — Datenmodell rekonstruieren
Die 764 Migrationsskripte maschinell zu einem Schemabild zusammenführen (Tabellen, Spalten, Typen, Indizes) und gegen die 983 NHibernate-Zuordnungen abgleichen. Damit entstünde erstmals ein belegtes, vollständiges Datenmodell — Grundlage jeder Datenmigration.
### Rang 6 — Traceability spiegeln und Lokalisierung auswerten
Alle Verweise beidseitig notieren. Die Ressourcendateien inhaltlich auswerten, um die Abdeckungslücke der englischen Fassung (rund 55 KB Differenz im WPF-Client) zu quantifizieren und deutschsprachige Literale im Backend systematisch zu erfassen.
---
## 8. Methodische Anmerkungen zu diesem Lauf
**Was gut funktioniert hat:**
- Die maschinelle Auszählung von Attributen, Endpunkten, Dateien und Konstanten lieferte belastbare, überprüfbare Kennzahlen ohne Interpretationsspielraum. Der Befund „221 Endpunkte ohne `[Authenticate]`" wäre durch Lesen nicht gefunden worden.
- Die Trennung von `Fakt` und `Aussage` erwies sich als wirksam: Bei SwRS-026 lässt sich dadurch klar sagen, dass der Ist-Zustand gesichert und nur die Soll-Aussage hypothetisch ist — was für die Validierung einen erheblichen Unterschied macht.
- Die Belegklassifikation zwang dazu, die umfangreiche `docs/`-Sammlung konsequent als `KONTEXT` zu behandeln. Dadurch wurden die dokumentationsgestützten Schwachstellen (Abschnitt 5.4) überhaupt sichtbar.
**Was die Ergebnisqualität begrenzt hat:**
- **Größenverhältnis.** 114 Anforderungen stehen 14 782 Quelldateien gegenüber. Die Auswahl der gelesenen Stellen ist die entscheidende Qualitätsgröße dieses Verfahrens — und sie beruhte auf Heuristiken (Dateigröße, Verzeichnisname, Rechtekonstanten als Wegweiser), nicht auf einer systematischen Abdeckungsstrategie.
- **Dokumentationssog.** Wo `docs/` eine fertige Architekturbeschreibung lieferte, wurde die Codeverifikation zurückgestellt. Das erklärt die Häufung dünner Belege genau in den architekturbeschreibenden Anforderungen.
- **Keine Ausführung.** Zustandsübergänge, Nebenläufigkeitsverhalten und tatsächliche Antwortzeiten sind nicht überprüfbar. Alle Performance- und Zuverlässigkeitsanforderungen beruhen auf Konfigurationswerten und Codestrukturen, nicht auf Messungen.
- **Change-Historie nur gestreift.** Von 52 135 Commits wurden 30 gelesen. Die Historie hätte Aufschluss über Änderungshäufigkeit, Fehlerschwerpunkte und faktische Nutzung der abgekündigten Bereiche geben können.
@@ -0,0 +1,160 @@
# Glossar
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
Alle in `StRS.md`, `SyRS.md` und `SwRS.md` verwendeten Domänen- und Systembegriffe. Jeder Eintrag nennt den Beleg im Quellcode. Technische Bezeichner (Klassen, Methoden, Spalten, Aufzählungswerte) bleiben in ihrer Originalsprache.
**Lesehilfe zur Zweisprachigkeit:** Die Codebasis führt viele Begriffe doppelt — deutsch in den historischen Datenbanktabellen, englisch in den modernen Entitäten und Sichten. Wo das zutrifft, sind beide Formen angegeben.
---
## A. Belegwesen
| Begriff | Definition | Beleg |
|---|---|---|
| **Beleg** (engl. *Receipt*) | Oberbegriff für alle Geschäftsdokumente mit Kopf- und Positionsdaten, Nummer, Datum, Version und Zustand. Umfasst sieben Kundenbeleg- und fünf Lieferantenbelegarten. | `Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` |
| **Kundenbeleg** | Beleg gegenüber einem Kunden: Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag. | `CentronObjectKindNumeric.IsCustomerReceipt` |
| **Lieferantenbeleg** | Beleg gegenüber einem Lieferanten: Anfrage (*SupplierOffer*), Bestellung (*SupplierOrder*), Wareneingang (*SupplierDeliveryList*), WE-Kalkulation (*SupplierInvoice*), Lieferantengutschrift (*SupplierCreditVoucher*). | `CentronObjectKindNumeric.IsSupplierReceipt` |
| **Angebot** / *Offer* | Unverbindliches Preisangebot. Tabelle `AngKopf`/`AngPos`, Sicht `Offers`/`OfferItems`, Objektart 1. | `ReceiptOffer.cs`; `CentronObjectKindNumeric.OfferClass` |
| **Auftrag** / *Order* | Verbindliche Kundenbestellung. Tabelle `AufKopf`/`AufPos`, Sicht `Orders`/`OrderItems`, Objektart 2. | `ReceiptOrder.cs`; `OrderClass` |
| **Lieferschein** / *Delivery List* | Warenbegleitpapier. Tabelle `LiefKopf`/`LiefPos`, Sicht `DeliveryLists`, Objektart 3. | `ReceiptDeliveryList.cs`; `DeliveryListClass` |
| **Rechnung** / *Invoice* | Zahlungsforderung. Tabelle `RechKopf`/`RechPos`, Sicht `Invoices`, Objektart 4. | `ReceiptInvoice.cs`; `InvoiceClass` |
| **Abholschein** / *Pickup List* | Beleg über die Abholung durch den Kunden. Tabelle `AbholKopf`/`AbholPos`, Objektart 5. | `ReceiptPickupList.cs`; `PickupListClass` |
| **Gutschrift** / *Credit Voucher* | Rückerstattung oder Korrektur. Tabelle `GutKopf`/`GutPos`, Objektart 6. | `ReceiptCreditVoucher.cs`; `CreditVoucherClass` |
| **Vertrag** / *Contract* | Wiederkehrend abzurechnende Leistungsvereinbarung. Tabelle `VertragKopf`/`VertragPos`, Objektart 22. | `ReceiptContract.cs`; `ContractClass` |
| **Belegzustand** / *ReceiptState* | Genau einer von drei Werten: `Active = 1` („offen"), `Completed = 2` („abgeschlossen"), `Canceled = 3` („storniert"). | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| **Belegversion** | Fortlaufende Ganzzahl je Beleg. Zulässig sind beim Speichern nur die Erstversion (1), die aktuelle oder die unmittelbar folgende Version. Vorgängerstände liegen in `*KopfVersions`/`*PosVersions`. | `ReceiptBL.cs:3568-3578, 3117` |
| **Beleg-Muster** / *Receipt Template* | Wiederverwendbare Belegvorlage, erkennbar an einer **negativen** Belegnummer (`IsTemplate => Number < 0`) und dem festen Ersatzdatum 01.01.1970. | `ReceiptBase.cs:65`; `ReceiptBL.cs:3586-3593` |
| **Weiterverarbeitung** / *Forwarding* | Erzeugung eines Folgebelegs aus einem Ursprungsbeleg (z. B. Auftrag → Lieferschein). Positionsherkunft über `IReceiptItemWithOrigin.OriginKind`. | `ReceiptWebServiceBL.ForwardReceipt`; `ReceiptBL.GetReceiptForwardedInto` |
| **Nummernkreis** / *NumberGroup* | Je Belegart und Filiale geführter Zähler mit Startwert (`Current`), Intervall (`Interval`) und Wertebereich (`RangeFrom`/`RangeTo`). | `Centron.Data.Entities.Administration.Company.NumberGroup`; `NumberGroupBL.cs` |
| **Kontingent** / *Contingent* | In einem Vertrag vereinbartes Guthaben an Stunden oder Beträgen, das durch Leistungen verbraucht wird. Felder `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentBalance*`. | `ReceiptContract`; `ReceiptContractHelperBL.cs` |
| **Anzahlung** / *Down Payment* | Teilzahlung vor vollständiger Leistungserbringung; eigene Abrechnungslogik. | `Sales/Receipts/DownPayment/DownPaymentBL.cs` |
| **Kreditlimit** / *Credit Limit* | Kundenbezogene Obergrenze der offenen Belegsumme. Berechnung netto (`CreditLimitCalculationKind == 1`) oder brutto; Wert `2` oder `null` deaktiviert die Prüfung. | `ReceiptBL.CheckIfCustomerLimitIsReached` |
| **Mindestpreis** / *MinPrice* | Artikelbezogener Preis, der ohne das Recht `ALLOW_IGNORE_MINIMUM_PRICE` nicht unterschritten werden darf. | `ReceiptBL.CheckArticleMinPrices`; `Article.MinPrice` |
| **Aktionspreis** | Zeitlich befristeter Sonderpreis eines Distributors oder Herstellers. Tabelle `HerstellerArtikAktionspreis`. | `ActionPriceBL.cs`; `docs/reference/receipts/actionprice-system.md` |
| **Preisspiegel** | Vergleichende Übersicht der Einkaufspreise eines Artikels über bis zu sieben parallele Quellen (ITscope, Artikelimport, COP, NEOS, TradersGuide, EGIS, Aktionspreise). | `PriceMatrixViewModel`; `ArticleSearchBL.cs` |
---
## B. Abrechnung und Finanzen
| Begriff | Definition | Beleg |
|---|---|---|
| **Abrechnungsintervall** / *BillingIntervalKind* | `Daily = 0` („Tag(e)"), `Monthly = 1` („Monat(e)"), `Yearly = 2` („Jahr(e)"), `Quarterly = 3` („Quartal(e)"). Kombiniert mit `BillingIntervalDuration` (Anzahl). | `Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs` |
| **Abrechnungsweise** / *BillingKind* | `Billingadvance = 0` („vorschüssig") oder `Billingarrear = 1` („nachschüssig"). | `BillingKind.cs` |
| **Abrechnungsauslösung** / *ContractCalculationKind* | Flags-Aufzählung: `None = 0`, `Auto = 1` („automatische Abrechnung"), `Need = 2` („Abrechnung nach Bedarf"), `Manual = 4` („manuell Abrechnung"). | `ContractCalculationKind.cs` |
| **Kontingentgrenze** / *ContingentLimitKinds* | `Percent = 0` oder `Absolute = 1`. | `ContingentLimitKinds.cs` |
| **Vertragsabrechnung** / *AutomaticFactura* | Automatisierte Erzeugung von Rechnungen aus fälligen Verträgen. | `AutomaticFacturaBL.Contracts.cs`; `AutomaticFacturaWebServiceBL.cs` |
| **Mahnstufe** / *DunningLevel* | `None`, `Level1`, `Level2`, `Level3`. Ab einer belegartspezifischen Sperrstufe blockiert sie das Anlegen neuer Belege. | `Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs`; `ReceiptBL.cs:10205-10216` |
| **Offene Posten (OPOS)** | Noch nicht ausgeglichene Forderungen. Eigenes Modul und Objektart `OPOS = 7600101`. | `OposOverviewAppModuleController`; `CentronObjectKindNumeric.OPOS` |
| **Provisionsschema** | Regelwerk zur Ermittlung von Vertriebsprovisionen, kundenbezogen zugeordnet und zeitlich befristet. | `ReceiptProvisionSchema.cs`; `ReceiptProvisionBL.cs` |
| **ZUGFeRD** | Deutscher Standard für hybride elektronische Rechnungen (PDF/A mit eingebettetem XML). Im System unterstützte Fassungen: `ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2`, `_2_0`, `_2_2`, `_2_3_1`, `_3_0_1`. | `InvoiceZugferdBL.cs`; `ZugferdKind` |
| **XRechnung** | Verbindliches Rechnungsformat für öffentliche Auftraggeber in Deutschland; im System durch die Angabe einer Leitweg-ID ausgelöst. | `InvoiceZugferdBL.cs:153-156, 193` |
| **Leitweg-ID** | Kennung des öffentlichen Rechnungsempfängers. Ihr Vorhandensein schaltet das System von `ZugferdFileKind.Comfort` auf `.XInvoice` und die PDF-Konformitätsstufe von `EN16931` auf `XRechnung` um. | `InvoiceZugferdBL.GenerateZugferdFile` |
| **EN 16931** | Europäische Norm für die semantische Struktur elektronischer Rechnungen; im System als PDF-Konformitätsstufe verwendet. | `PdfZugferdConformanceLevel.EN16931` |
| **Kontenrahmen** / *AccountSystem* | Gliederung der Sachkonten für die Finanzbuchhaltung. | `AccountSystemsAppModuleController`; `BookKeepingAccountSystems` |
| **Mandat** / *SEPA-Mandat* | Einzugsermächtigung des Kunden. Objektart `SepaContract = 7600087`. | `ReceiptBL.CheckIfMandatIsNeeded`; `ReceiptContract.MandatI3D` |
| **ESR** | Schweizer Einzahlungsschein mit Referenznummer; eigene Feldbefüllung für Schweizer Belege. | `Sales/Receipts/Internal/ReceiptEsrBL.cs`; `IReceiptWithEsr` |
---
## C. Service und Ticketwesen
| Begriff | Definition | Beleg |
|---|---|---|
| **Helpdesk / Ticket** | Serviceanfrage eines Kunden. Objektart `HelpdeskClass = 10`, Tabelle `hlpdsk_requests`. | `HelpdeskBL.cs`; `CentronObjectKindNumeric.HelpdeskClass` |
| **Ticketzustand** | Anwenderpflegbares Stammdatum – **keine** feste Aufzählung im Code. Der Abschlusszustand wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfiguriert. | `HelpdeskBL.cs:433` |
| **Helpdeskzeit** / *HelpdeskTimer* | Erfasste Arbeitszeit an einem Ticket, verknüpfbar mit einer Belegposition. Objektart `HelpdeskTimerClass = 4000056`. | `HelpdeskTimerBL.cs`; `ReceiptItemTimerBL.cs` |
| **Mitarbeiterartikel** | Artikel, der einen Mitarbeiter für die Zeitabrechnung repräsentiert. | `EmployeeArticlesController.cs`; `CentronRights.md:50-53` |
| **Eskalation** | Regelbasierte Höherstufung eines Tickets bei Fristüberschreitung. Objektart `EscalationServer = 7600097`. | `Sales/Support/Escalation/EscalationBL.cs`; `EscalationsService.cs` |
| **Ticketvorlage** / *TicketPattern* | Vorlage zur automatisierten Ticketerstellung (C-FLOW). Objektart `TicketPattern = 7600093`. | `HelpdeskPatternBL.cs`; `TicketPatternsController.cs` |
| **C-FLOW** | Ticketprozess-/Vorlagensystem mit eigenem Rechteblock. | `UserRightsConst.Sales.Customer.Helpdesk.CFlow` |
| **Checkliste** | Strukturierte Aufgabenliste an einem Ticket. Objektart `Checklist = 7600082`. | `CheckListArea/`; `ChecklistsController.cs` |
| **Stammblatt** / *MasterDataList* | Geräte-/Anlagenverzeichnis eines Kunden, verknüpfbar mit Verträgen. Objektart `MasterDataListClass = 25`. | `ReceiptContractBL.AddMasteDateListsToContract` |
| **Web-Anfragezustand** / *RequestStateEnum* | Feste Aufzählung für Portalanfragen: `Requested = 0` („Angefragt"), `Veryfied = 1` („Verifiziert"), `Accepted = 2` („Angenommen"), `Denied = 3` („Abgelehnt"). | `RequestStateEnum.cs` |
---
## D. Lager und Artikel
| Begriff | Definition | Beleg |
|---|---|---|
| **Artikel** | Handelbare Ware oder Leistung. Objektart `Article = 9`. | `Warehousing/ArticleBL.cs` |
| **Warengruppe** / *MaterialGroup* | Klassifikation von Artikeln. Objektart `MaterialGroup = 70`, Nebenwarengruppe `SecondaryMaterialGroup = 136`. | `MaterialGroupBL.cs` |
| **Barcode / Seriennummer** | Eindeutige Kennung eines Einzelstücks. Artikel mit `NeedsBarcodes = true` verlangen je Positionsmenge einen erfassten Barcode. | `ReceiptBarcodeBL.cs`; `IReceiptItemWithBarcodes` |
| **Negative Lagerbuchung** | Buchung, die den Bestand unter null senkt **und** ihn dabei verringert. Eine Buchung, die einen bereits negativen Bestand anhebt, gilt ausdrücklich nicht als solche. | `ReceiptArticleBookingBL.cs:357-362` |
| **Kommissionierung** / *Commissioning* | Zusammenstellung der Ware für einen Auftrag, auch als Teilkommissionierung. | `PartialCommissionOrderBL.cs`; `OrderCommissionBL.cs` |
| **Inventur** / *Inventory* | Periodische Bestandsaufnahme mit eigenem Rechteblock (9 Rechte). | `InventoryBL.cs`; `UserRightsConst.Purchase.Inventory` |
| **RMA** | Rücksendevorgang (*Return Merchandise Authorization*). Objektarten `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145`. | `CustomerArea/RmaBL.cs` |
---
## E. Berechtigung, Identität, Lizenz
| Begriff | Definition | Beleg |
|---|---|---|
| **Recht** / *AppRight* | Numerisch identifizierte Berechtigung, hierarchisch über `AppRight.Parent`. Tabelle `Sichrech`. Neue .NET-Rechte beginnen bei 20800000. | `UserRightsConst.cs`; `AppRightsBL.cs` |
| **Rechtegruppe** / *AppGroup* | Bündel von Rechten, optional filialbezogen (`BranchI3D`). Tabelle `Sichgrup`; Zuordnungen in `Sichtrus` (Gruppe↔Recht) und `Sichmemb` (Benutzer↔Gruppe). | `AppRightsBL.cs:651-664` |
| **Einschränkendes Recht** | Recht, dessen **Besitz** den Zugriff verengt statt ihn zu gewähren (z. B. `SHOW_HELPDESK_ONLY_OWN`). „nur eigene" hat Vorrang vor „nur eigene Filiale". | `HelpdeskBL.cs:269-291`; `CentronRights.md:9-17` |
| **Administratorgruppe** | Gruppe mit `I3D == 6` oder dem Namen „Administratoren". Nicht löschbar; ihre Rechtezuordnungen sind nur für 41 gelistete Rechte änderbar. | `AppRightsBL.cs:348-374, 714-759` |
| **Benutzer** / *AppUser* | Systemkonto eines Mitarbeiters, Tabelle `Sichbenu`. Trägt `AuthentificationKind`, `IsAccountDisabled`, `AccountDisabledFromDate`/`ToDate`, `LoginIP`. | `Centron.Data.Entities.Administration.AppUser` |
| **Web-Account** | Portalkonto eines Kundenansprechpartners mit **eigenem**, direkt kontobezogenem Rechtemodell (Tabelle `WebAccountsRights`). Kein Zugriff auf das interne Belegwesen. | `WebAccountBL.cs`; `WebAccountRightsConst`; `ReceiptBL.cs:10297-10302` |
| **Anwendungsart** / *ApplicationKind* | Eine der 44 anmeldefähigen Anwendungen mit Lizenz-GUID, Ticketablaufart, Lizenzzählweise sowie optional erforderlichem oder verbietendem Recht. | `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| **Sitzungsticket** / *Ticket* | Zeitlich begrenzte Sitzungskennung, gebildet aus einem 32-Zeichen-Zufallssalz und dem Gerätenamen. Gültigkeitsdauer je Anwendungsart: 5 Minuten (Monitoring), 30 Minuten (Standard), 1 440 Minuten (Tagesticket) oder aus Einstellung, mindestens 30 Minuten. | `TicketBL.cs:26-28, 136-170` |
| **Lizenz** | GUID, die den Besitz eines Produkts oder Einzelmerkmals darstellt; ergänzt um Anzahl, Gültigkeitsdatum und Gültigkeitsversion. 159 GUIDs definiert. | `LicenseGuids.cs`; `docs/reference/security/licensing-system.md` |
| **Lizenzzählweise** / *LicenseUsageKind* | `PerUserAndPerMachine` (Standard) oder `PerUser` (z. B. ServiceBoard). Bestimmt, wie belegte Lizenzen gezählt werden. | `ApplicationKind.cs`; `TicketBL.GetTicketCount` |
| **Zwei-Faktor-Authentifizierung** | Zweiter Anmeldefaktor über `RadiusServer` oder `EmailLink`. Gültigkeit je Benutzer in Tagen; `0` bedeutet: bei jeder Anmeldung. Gemerkt je Benutzer, Anwendung, Maschine und IP-Adresse. | `TwoFactorAuthBL.cs:33-193` |
---
## F. Organisation und Stammdaten
| Begriff | Definition | Beleg |
|---|---|---|
| **Mandant** / *Mandator* | Rechtliche Einheit im System. Objektart `Company = 53`. Nummernkreise werden stets auf dem Standardmandanten geführt. | `MandatorBL.cs`; `NumberGroupBL.cs:144-151` |
| **Filiale** / *Branch* | Organisatorische Untereinheit. Objektart `Branch = 124`. Belege tragen `BranchI3D`; ein Wert von `null` oder `0` bezeichnet die Standardfiliale. | `BranchBL.IsBranchEqual`; `ReceiptBL.cs:10258-10267` |
| **Filialherkunft** / *BranchOrigin* | Regel zur Ermittlung der Belegfiliale: `Creator` (Ersteller) oder `Adviser2` (Außendienstbetreuer). | `ReceiptBL.GetBranchForNewReceipt` |
| **Betreuer 1 / Adviser1** | Innendienstbetreuer eines Belegs, Feld `OfficeStaffI3D`. | `UserRightsConst…CHANGE_ADVISER1`; `ReceiptContract.OfficeStaffI3D` |
| **Betreuer 2 / Adviser2** | Außendienstbetreuer eines Belegs, Feld `SalesRepresentativeI3D`. | `UserRightsConst…CHANGE_ADVISER2` |
| **Kunde** / *Customer* | Objektart `Customer = 12` bzw. `CustomerClass = 5000012`; Legacy-Tabelle `Kunden`. | `CustomerBL.cs` |
| **Kreditor / Lieferant** | Objektart `Creditor = 20`; Legacy-Tabelle `Kreditor`. | `NumberGroupBL.cs:124-131` |
| **Ansprechpartner** / *ContactPerson* | Objektart `ContactPerson = 19`; Träger personenbezogener Daten und damit Gegenstand der DSGVO-Anonymisierung. | `ContactPersonBL.cs`; `DataSecurityBL.cs` |
| **Konto** / *Account* | Neueres, kunden- und lieferantenübergreifendes Adressmodell. Objektart `Account = 7600071`. Ersetzt bei aktivierter Einstellung `IsAccountManagementActive` den Adressstamm. | `AccountBL.cs`; `ModuleRegistration.cs:522-529` |
---
## G. Technische Systembegriffe
| Begriff | Definition | Beleg |
|---|---|---|
| **I3D** | Standardname des Primärschlüssels aller Tabellen (`int IDENTITY(1,1) NOT NULL`, gruppierter Primärschlüsselindex). Fremdschlüssel enden auf `I3D` mit dem Namen der referenzierten Tabelle als Präfix. | `docs/guides/database/database-conventions.md:12-35` |
| **Objektart** / *CentronObjectKindNumeric* | Stabile numerische Kennung eines Geschäftsobjekttyps; 205 Werte. Polymorphe Verweise werden als Paar `ObjectI3D` + `ObjectKind` (Legacy: `AnlageI3D` + `AnlageArt`) geführt. | `Centron.Interfaces/CentronObjectKindNumeric.cs` |
| **`Result<T>`** | Einheitliches Ergebnisobjekt aller Fachmethoden mit `Status` (`Success`/`Error`/`Warning`), `Message`, `MessageCode` und `Data`. Ersetzt Ausnahmen als Fehlerkanal. | `docs/getting-started/general-structure.md:30-35` |
| **ILogic / BLLogic / WSLogic** | Dreiteiliges Zugriffsmuster im Client: eine Schnittstelle mit zwei Implementierungen — direkter Datenbankzugriff (`BL*Logic`) und Web-Service-Aufruf (`WS*Logic`). | `docs/getting-started/general-structure.md:36-113` |
| **ClassContainer** | Singleton für die Auflösung der `ILogic`-Schnittstellen im Client. | `ClassContainer.Instance.WithInstance(...)` |
| **BLSession / DAOSession** | Sitzungsfassade für Fachlogik, Entitätszugriff, Repositories, parametrisiertes Roh-SQL, Zwischenspeicher und Transaktionsklammer. | `AppRightsBL.cs:105-110`; `ReceiptBL.cs:3544` |
| **SpecificLogic** | Belegartspezifische Strategieimplementierung von `IReceiptSpecificLogic`; 13 Ausprägungen. `ReceiptBL` delegiert jede belegartabhängige Entscheidung dorthin. | `IReceiptSpecificLogic.cs`; `Sales/Receipts/*/…SpecificLogic.cs` |
| **WebServiceBL** | Schicht zwischen Fachlogik und Schnittstelle; wandelt Entitäten in DTOs und zurück (AutoMapper-Profile unter `WebServices/ObjectMapperConfiguration/`). | `ReceiptWebServiceBL.cs` |
| **ScriptMethod** | Nummerierte, idempotente Datenbankskriptklasse (`ScriptMethod{Nummer}.cs`), beim Start des Web-Service ausgeführt. 764 Skripte vorhanden. | `Administration/Scripts/ScriptMethods/Scripts/`; `docs/reference/database/script-rules.md` |
| **ApplicationSettings** | Aktuelle Einstellungstabelle mit 492 Bezeichnern in `ApplicationSettingID`, je Eintrag mit Beschreibung. | `ApplicationSettingID.cs`; `ApplicationSettingDefinitions.cs` |
| **Stammdat** | Historische Einstellungstabelle mit 728 Bezeichnern in `AppSettingsConst`. Wird weiter gelesen und geschrieben, nimmt aber keine neuen Einstellungen mehr auf. | `AppSettingsConst.cs`; `docs/guides/development/settings-management.md:16-23` |
| **ChangeLog** | Feldgenauer Änderungsprotokolleintrag mit `ObjectI3D`, `ObjectKind`, `Property`, `OldValue`, `NewValue`, `Date`, `AppUser`. Erzeugt vom NHibernate-Ereignisempfänger für attributierte Entitäten. | `ChangeTrackingEventListener.cs` |
| **AnlageLog** | Historische, belegartübergreifende Protokolltabelle mit `AnlageI3D` + `AnlageArt`. | `docs/reference/receipts/receipts-backend-architecture.md:123-143` |
| **Versionstabelle** | Strukturgleiche Kopie einer Belegtabelle (`*KopfVersions`, `*PosVersions`), ergänzt um `OriginalI3D` und – bei Positionen – `KopfVersionsI3D`. | `docs/reference/receipts/receipts-backend-architecture.md:147-204` |
| **Temporäre Legacy-Entität** | Zwischenschicht des Schreibpfads: moderne Belegentitäten werden vor dem Speichern in Entitäten der deutschen Legacy-Tabellen übertragen. | `Centron.Entities/Entities/DbEntities/`; `SaveReceipt*Repository` |
| **ManagedBackgroundService** | Gemeinsame Basisklasse aller 35 Hintergrunddienste; regelt Anlaufverzögerung, Aktivierung, Fehlerbehandlung, Frequenzrücknahme und Laufzeitprotokollierung. | `Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs` |
| **Nexus** | Blazor-Server-Webportal, ausgeliefert unter der Marke „NEXOWARE ServiceBoard"; enthält ServiceBoard, WebCart, WebOffer und C-Sign. | `src/nexus/CentronNexus/`; `appsettings.json` (`Branding.Title`) |
| **WebCart** | Bestellportal für Endkunden des Anwenders; zeigt Artikel aus deren Sonderpreisen. | `src/nexus/CentronNexus/WebCart/`; `README.md:31-36` |
| **C-Sign** | Verfahren zur tokengebundenen Bereitstellung, Annahme und handschriftlichen Signatur von Dokumenten durch externe Empfänger. Objektarten `DocumentSigning = 7600133`, `DocumentSigningCustomerReceipts = 7600146`. | `DocumentSigningPage.razor`; `SignSharedDocument` |
| **RMM** | *Remote Monitoring and Management* – externes Überwachungssystem, aus dem nutzungsbasierte Abrechnungsmengen bezogen werden. Platzhalter `@@RMMArtikel@@` in der Rechnungsvorlage. | `AutomaticFacturaWebServiceBL.CheckRMMArticle`; `RiverConnectionBL` |
| **MSP** | *Managed Service Provider* – Betriebsmodell des Anwenderunternehmens; eigene Auswertungsmodule (`MspCollector`, `MSPComparer`, `MspDashboard`). | `UserRightsConst.MspCollector`; `ModuleRegistration.cs:651-661` |
| **EDI** | *Electronic Data Interchange* – elektronischer Belegaustausch mit Distributoren. Formate: OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron, ZUGFeRD. | `SupplierEdiBL.cs`; `Centron.Gateway/EDI_*` |
| **DSGVO-Löschung** | Anonymisierung statt physischer Löschung: personenbezogene Felder werden geleert, der Datensatz wird mit `IsDsgvoDeleted`, `DsgvoDeletedEmployeeI3D` und `DsgvoDeletedDate` gekennzeichnet; jeder entfernte Wert wird protokolliert. | `DataSecurityBL.cs:1195-1284` |
---
## H. Nicht verwendete, aber im Code vorhandene Begriffe
Diese Begriffe treten im Code auf, sind aber als `[Obsolete]` gekennzeichnet und wurden bewusst **nicht** in Anforderungen überführt (siehe `StRS.md`, Abschnitt 3, und `Hypothesen.md`, B-03):
**Riversuite**, **RiverSuiteCommonRights**, **Monitoring** (RMM-Vorgängersystem), **SupRemo** (Fernwartung), **DirectNow** (Echtzeitverbindung), **N13**, **Kassenbuch** / **Barrechnung** (`Sales.Cashbox`), **Dokumentationskategorien** (`Documentation.Categories`), **Telemarketing** (`RIGHT_SONDERAKTIONEN`).
@@ -0,0 +1,158 @@
# Hypothesen
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
Diese Datei sammelt alle Aussagen der Spezifikation, die sich **nicht eindeutig** aus den Artefakten ableiten lassen. Jede Hypothese nennt die offene Frage, die zur Bestätigung fehlende Information und den empfohlenen Klärungsweg. Sie sind der priorisierte Eingang in Schritt 7 der RRE-Methodenkette (Validierung durch Fachexperten).
**Anzahl:** 6 formal als `Status: HYPOTHESE` gekennzeichnete Anforderungen, ergänzt um 4 Beobachtungen ohne eigene Anforderung.
---
## A. Formal gekennzeichnete Hypothesen
### H-01 · SyRS-011 — Autorisierung der 221 nicht attributierten Legacy-Endpunkte
**Risikoklasse:** Sicherheit (höchste Priorität)
**Was belegt ist:** Von 2 599 Methoden der Legacy-REST-Schnittstelle tragen 2 374 das Attribut `[Authenticate]`. 221 Methoden tragen es nicht. Für einen Teil ist der anonyme Zugriff fachlich beabsichtigt und über einen Token bzw. eine GUID im Anfrageobjekt gesichert (`GetSharedDocumentByToken`, `SignSharedDocument`, `GetWebFormByGuid`, `GetWebRequestPageByGuid`, `GetWebLinkByGuid`) oder betrifft die Anmeldung und Auskunftsfunktionen (`Login`, `Logout`, `AuthenticateLogin`, `GetWebserviceVersion`, `GetSystemTime`, `GetDatabaseVersion`).
**Was nicht belegt ist:** Für schreibende Fachoperationen ohne erkennbaren Tokenschutz — nachgewiesen für `SaveCustomerSpecialArticle`, `DeleteCustomerSpecialArticle`, `SaveLogo`, `DeleteLogo`, `SaveOrUpdateContractExternalArticleImportHead`, `DeleteContractExternalArticleImportHead`, `SaveOrUpdateContractExternalArticleImportPositions`, `SaveAppointmentRequest`, `HandleAppointmentRequestReply`, `UpdateModuleFavorite`, `UpdateIgnoreRequiredFieldsSetting`, `UpdateWebAccountHelpdeskSettings`, `AssignTicketPatternToHelpdesk`, `CreateTicketPatternChildrenForTicket`, `CreateHelpdeskFromHelpdeskPattern`, `GetWebServiceMethodList` — ist kein alternativer Zugriffsschutz an der Methodensignatur erkennbar.
**Offene Frage:** Nimmt der WCF-/ASP.NET-Core-Bridge-Interceptor (`Centron.Host.AspNetCore.WcfBridge.Interception`) eine implizite Standardauthentifizierung für nicht attributierte Methoden vor — oder sind diese Endpunkte tatsächlich unauthentifiziert erreichbar?
**Fehlende Information:** Die Implementierung der Interception-Bridge liegt nicht als analysierbare Quelle im untersuchten Attributpfad; nur das Attribut selbst (`AuthenticateAttribute.cs`) war lesbar.
**Klärungsweg:** Laufzeitprüfung gegen eine Testinstanz (Aufruf von `DeleteLogo` ohne Ticket) **oder** Codeeinsicht in die Bridge durch die Entwicklung. Bei Bestätigung: sicherheitskritischer Befund mit sofortigem Handlungsbedarf, unabhängig von der Neuimplementierung.
**Belege:** `src/webservice/Centron.Host/Services/ICentronRestService.cs` (Deklarationen ohne `[Authenticate]`); `src/webservice/Centron.WebServices.Core/Interception/Interceptors/AuthenticateAttribute.cs`
---
### H-02 · SwRS-026 — Ablösbarkeit der ungesalzenen SHA-1-Kennwortspeicherung
**Risikoklasse:** Sicherheit (höchste Priorität)
**Was belegt ist — der Ist-Zustand, eindeutig durch `PRIMÄR`-Belege:** Kennwörter werden als **ungesalzener SHA-1-Wert** gespeichert und geprüft. `BasicAuthenticator.AuthenticateInternal` bildet `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` und sucht den Benutzer direkt über `where.Name == UserName && where.Password == decodedPassword` — das Kennwort ist damit Teil der Datenbankabfrage, ein Vergleich in konstanter Zeit findet nicht statt. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. `WebAccountBL.LoginWithWebAccount` verwendet dasselbe Verfahren für Portalkonten. Eine gesalzene Ableitungsfunktion (`CryptoUtils.CreateSalt(32)`, `CryptoUtils.CreatePasswordHash`) ist im System vorhanden, wird aber ausschließlich für Ticketkennungen verwendet.
**Was nicht belegt ist — die Soll-Aussage:** Ob eine Umstellung auf ein gesalzenes, rechenintensives Verfahren (z. B. PBKDF2, bcrypt, Argon2) im Zielsystem umsetzbar ist.
**Offene Frage:** Welche Randbedingungen bestehen für eine Migration der bestehenden Kennwörter — insbesondere: Greift die Delphi-Vorgängeranwendung „c-entron Delphi" weiterhin auf denselben Benutzerstamm (`Sichbenu`) zu und erwartet dort den SHA-1-Wert?
**Fehlende Information:** Der Zugriffspfad der Delphi-Anwendung auf die Kennwortspalte liegt außerhalb des Arbeitsverzeichnisses. `LicenseManager.TryFixCentronDelphiVersionNumber` belegt zwar, dass die Delphi-Anwendung dieselbe Lizenz und damit denselben Datenbestand nutzt, sagt aber nichts über den Anmeldepfad aus.
**Klärungsweg:** Aussage der Entwicklung zur Delphi-Kompatibilität und zur geplanten Ablösung. Prüfidee zum Nachweis des Ist-Zustands: Zwei Benutzer mit identischem Kennwort besitzen in der Datenbank denselben Kennwortwert.
**Belege:** `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50`; `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:56-61`; `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:166-170`
---
### H-03 · SyRS-041 — Transportverschlüsselung als Vorgabe
**Risikoklasse:** Sicherheit
**Was belegt ist:** Die ausgelieferten Beispiel- und Betriebskonfigurationen verwenden **unverschlüsseltes HTTP**: `WebServiceConfig.xml` enthält `<WebServiceAddress>http://localhost:1234/CentronService</WebServiceAddress>` mit leeren Zertifikatsknoten; die Portalkonfiguration enthält `Host.Url = http://localhost:8050/` mit leeren Feldern `LinuxCertificatePath`/`LinuxCertificatePassword`. HTTPS ist über `WebServiceCertificateFilePath` und `WebServiceCertificatePassword` nachrüstbar und in der Linux-Anleitung beschrieben.
**Was nicht belegt ist:** Dass HTTPS in produktiven Kundeninstallationen verbindlich ist. Es existiert kein Artefakt, das HTTPS erzwingt oder als Vorgabe setzt.
**Offene Frage:** Ist HTTPS in Kundeninstallationen verbindlich vorgeschrieben, oder wird der Web-Service typischerweise unverschlüsselt in einem als vertrauenswürdig angenommenen Netz betrieben?
**Fehlende Information:** Betriebsvorgabe außerhalb der Codebasis (Installationshandbuch, Vertragsanlage, Betriebskonzept).
**Klärungsweg:** Aussage der Betriebs-/Supportorganisation. Für das Zielsystem ist HTTPS als Pflicht zu setzen; die Frage betrifft nur die Bewertung des Ist-Zustands.
**Nachgelagerter Befund:** Das Zertifikatskennwort steht laut `docs/guides/services/web-service-on-linux.md:116-119` im Klartext in der Konfigurationsdatei — dies ist in der Projektdokumentation ausdrücklich als offener Punkt benannt („we should `encrypt` the certificate-password instead").
**Belege:** `docker/compose/WebServiceConfig.xml`; `src/nexus/CentronNexus.Host/appsettings.json`; `docs/guides/services/web-service-on-linux.md:35-58, 116-119`
---
### H-04 · SyRS-042 — Schutz vor E-Mail-Versand an Echtempfänger in Entwicklungsständen
**Risikoklasse:** Sicherheit / Datenschutz (mittel)
**Was belegt ist:** In der Docker-Entwicklungsumgebung existiert ein Mailcatcher-Dienst (`centron.azurecr.io/mailcatcher`, Ports 1025/1080) mit eigenem Dockerfile, der ausgehende Nachrichten abfängt. Die Projektdokumentation beschreibt zusätzlich eine Klasse `DeveloperSecurity`, die in DEBUG-Builds alle externen E-Mail-Adressen durch `test@nexoware.com` ersetzt; als intern gilt jede Adresse mit der Endung `nexoware.com`. In RELEASE-Builds greift der Schutz ausdrücklich nicht.
**Was nicht belegt ist:** Die Existenz und Wirkungsweise der Klasse `DeveloperSecurity` im Code. Eine Datei `DeveloperSecurity.cs` konnte im Arbeitsverzeichnis nicht gefunden werden.
**Offene Frage:** Existiert die beschriebene Adressersetzung noch, oder ist die Dokumentation veraltet und der Schutz besteht nur noch aus dem Mailcatcher der Entwicklungsumgebung?
**Fehlende Information:** `PRIMÄR`-Beleg für die Adressersetzung im Code.
**Klärungsweg:** Gezielte Suche nach `AllowSendingEmailToExternalAddresses` bzw. `test@nexoware.com` im Code in einer Folge-Iteration; falls erfolglos, Aussage der Entwicklung.
**Belege:** `docs/reference/security/developer-security.md:11-25` (KONTEXT); `docker/compose/compose.yaml`, `docker/c-entron-mailcatcher/Dockerfile` (PRIMÄR)
---
### H-05 · SwRS-037 — Inhalt und Rechtsgrundlage der Telemetrieübertragung
**Risikoklasse:** Datenschutz (mittel bis hoch, abhängig vom Inhalt)
**Was belegt ist:** Es existieren die Hintergrunddienste `TelemetryFlushService` (Intervall 1 Minute), `TelemetryUploadService` (12 KB) und `FlushAnalyticEventsService`, der Fachbereich `src/backend/Centron.BL/Telemetry/` sowie 12 Telemetrieentitäten unter `Centron.Entities/Entities/Telemetry` (u. a. `TelemetryLicenseKind`). Der Klassenkommentar in `LicenseGuids.cs` belegt die Kopplung an den Lizenzbestand: „Task: Update TelemetryLicenseKind.cs … enum, when new licenses were added."
**Was nicht belegt ist:** Welche Daten konkret erhoben und an wen übertragen werden, ob ein Personenbezug besteht und ob die Übertragung abschaltbar ist.
**Offene Frage:** Welchen Umfang hat die Telemetrie, welche Rechtsgrundlage liegt zugrunde, und ist das Anwenderunternehmen darüber informiert?
**Fehlende Information:** `TelemetryUploadService.cs` und die 12 Telemetrieentitäten wurden in dieser Iteration nicht im Detail ausgelesen (Priorisierungsentscheidung, siehe `Analysebericht.md`).
**Klärungsweg:** Nachschlag in einer Folge-Iteration mit vollständiger Analyse des Telemetriedatenmodells; anschließend Abgleich mit der Datenschutzerklärung gegenüber dem Anwenderunternehmen.
**Belege:** `src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryUploadService.cs`; `src/backend/Centron.BL/Telemetry/`; `src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs:7`
---
### H-06 · SwRS-010 — Bewertung der reflexionsbasierten Auflösung generischer Belegoperationen
**Risikoklasse:** Wartbarkeit / Performance (niedrig)
**Was belegt ist:** `ReceiptBL.SaveReceipt(IReceiptBase, …)` und `ReceiptBL.CreateNewVersion(CentronObjectKindNumeric, …)` ermitteln die generische Überladung zur Laufzeit über Reflexion (`GetMethods().First(f => f.IsGenericMethod).MakeGenericMethod(...)`) und rufen sie per `Invoke` auf. Typfehler werden dadurch erst zur Laufzeit sichtbar.
**Was nicht belegt ist:** Ob die Reflexion eine bewusste Entwurfsentscheidung (z. B. wegen der nicht-generischen Signatur der Legacy-Schnittstelle) oder eine ablösbare Altlast ist.
**Offene Frage:** Kann die Auflösung im Zielsystem statisch typisiert erfolgen, oder erzwingt die aufrufende Schnittstelle die dynamische Auflösung?
**Fehlende Information:** Kommentar oder Entwurfsnotiz an der Codestelle; beide Methoden sind unkommentiert.
**Klärungsweg:** Aussage der Entwicklung. Die Frage betrifft die Zielarchitektur, nicht das Ist-Verhalten.
**Belege:** `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3517-3521, 3063-3067`
---
## B. Beobachtungen ohne eigene Anforderung
Diese Punkte sind belegt, waren aber im Rahmen dieser Iteration nicht ausreichend analysierbar, um daraus eine testbare Anforderung zu formulieren. Sie sind für die Validierung dokumentiert.
### B-01 · Kopiermechanik der Belegversionierung nicht im Detail gelesen
Die Aussage, dass Versionstabellen strukturgleiche Kopien sind und über eine dynamisch erzeugte Feldliste (`DoGetFieldList()`, `AssetHeadDAO.SaveAssetVersion`) befüllt werden, stützt sich auf die Projektdokumentation (`docs/reference/receipts/receipts-backend-architecture.md:147-204`) und den Aufrufpunkt im Speicherpfad (`ReceiptBL.cs:3629`). Die Implementierung in `AssetHeadDAO` wurde nicht gelesen. **Auswirkung:** SwRS-008 trägt daher den Zusatz `Workaround` und stützt sich überwiegend auf `KONTEXT`-Belege. **Nachschlag:** `Centron.DAO`-Analyse von `AssetHeadDAO.SaveAssetVersion`.
### B-02 · Konsistenz zwischen `AppRight.Text` und `UserRightsConst`
`UserRightsConst` definiert die Recht-IDs als Konstanten; die anwendersichtbaren Rechtebezeichnungen liegen dagegen in der Datenbanktabelle `Sichrech` im Feld `Text`. Ein Abgleich zwischen beiden ist im Code nicht erkennbar. **Offene Frage:** Wie wird sichergestellt, dass eine im Code eingeführte Recht-ID auch in der Datenbank mit einer Bezeichnung existiert? Die Datei `DefaultRightsStructure.txt` deckt nur die Standardgruppen ab, nicht die Rechtestammdaten selbst. **Auswirkung:** keine Anforderung formuliert; Frage betrifft die Datenpflege.
### B-03 · Abgekündigte Funktionsbereiche
Erhebliche Teile von `UserRightsConst` sind mit `[Obsolete]` gekennzeichnet: die vollständigen Blöcke `Monitoring` (17 Rechte), `SupRemo` (6), `DirectNow` (2), `Riversuite` (8), `RiverSuiteCommonRights` (3), `N13` (2), `Sales.Cashbox` (7) sowie zahlreiche Einzelrechte. Ebenso ist der Bereich `Documentation.Categories` vollständig abgekündigt. **Offene Frage:** Sind die zugehörigen Funktionen bei Kunden noch im Einsatz, oder können sie in der Neuimplementierung ersatzlos entfallen? **Auswirkung:** Diese Bereiche wurden bewusst aus dem Anforderungsumfang ausgeschlossen (siehe `StRS.md`, Abschnitt 3 „Abgrenzung"). Eine Fehleinschätzung würde Funktionslücken im Zielsystem verursachen.
### B-04 · Skriptnummernvergabe außerhalb der Versionsverwaltung
Die Nummernvergabe für Datenbankskripte (`ScriptMethod{Nummer}.cs`) erfolgt laut `docs/reference/database/script-rules.md:12-15` über eine externe, in Teams abgelegte Excel-Datei. Damit ist die Eindeutigkeit der Nummern nicht durch das Versionsverwaltungssystem gesichert. **Offene Frage:** Ist es in der Vergangenheit zu Nummernkollisionen gekommen, und wie wurden sie aufgelöst? **Auswirkung:** In SwRS-033 als `Workaround` vermerkt.
---
## C. Priorisierung für die Validierung
| Rang | Hypothese | Begründung |
|---|---|---|
| 1 | **H-01** (221 offene Endpunkte) | Unmittelbares Sicherheitsrisiko im Produktivsystem, unabhängig von der Neuimplementierung |
| 2 | **H-02** (SHA-1 ohne Salt) | Ist-Zustand gesichert; die Klärung betrifft nur die Migrationsstrategie, der Handlungsbedarf steht fest |
| 3 | **H-05** (Telemetrieinhalt) | Möglicher Personenbezug ohne bekannte Rechtsgrundlage |
| 4 | **B-03** (abgekündigte Bereiche) | Fehleinschätzung führt zu Funktionslücken im Zielsystem |
| 5 | **H-03** (HTTPS) | Betriebsfrage; im Zielsystem ohnehin als Pflicht zu setzen |
| 6 | **H-04** (E-Mail-Schutz) | Betrifft nur Entwicklungsstände |
| 7 | **B-01** (Versionierungsmechanik) | Detailfrage der Persistenz; durch Nachschlag im Code lösbar |
| 8 | **H-06** (Reflexion) | Reine Zielarchitekturfrage ohne Ist-Risiko |
| 9 | **B-02** (Rechtebezeichnungen) | Datenpflegefrage ohne funktionale Auswirkung |
| 10 | **B-04** (Skriptnummern) | Prozessfrage der Entwicklung |
@@ -0,0 +1,592 @@
# StRS – Stakeholder Requirements Specification
**System:** NEXOWARE c-entron ERP (c-entron.NET, c-entron Web-Service, c-entron Nexus / ServiceBoard, Outlook Add-In)
**Verfahren:** Reverse Requirements Engineering (statische Artefaktanalyse), ISO/IEC/IEEE 29148:2018
**Analysebasis:** Git-Arbeitskopie `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48` (Stand 2026-08-25)
**Erstellt:** 2026-08-25 · **Iteration:** V1 Baseline (Prompt-only), Lauf 01
---
## 0. Lesehinweise
- **Fakt** enthält ausschließlich die im Artefakt beobachtete technische Tatsache.
- **Aussage** enthält die daraus abgeleitete fachliche Soll-Aussage (Interpretation).
- Belegklassen: `PRIMÄR` = durchgesetzte Regel in Code oder DB-Constraint · `SEKUNDÄR` = UI-Label, Fehlermeldung, Mappingtabelle, Konfigurationsschalter, Reportlayout · `KONTEXT` = Kommentar, Commit-Message, Projektdokumentation, Ticketreferenz.
- Pfade sind relativ zur Repository-Wurzel.
- Alle Domänenbegriffe sind in `Glossar.md` definiert.
- Alle mit `[HYPOTHESE]` markierten Aussagen sind zusätzlich in `Hypothesen.md` gesammelt.
**Wichtige Abgrenzung zu Projektdokumentation:** Das Repository enthält unter `docs/` eine umfangreiche Entwicklerdokumentation. Diese wird durchgängig als `KONTEXT` klassifiziert, weil sie nicht ausführbar ist und vom Code abweichen kann. Wo eine Anforderung auf Sicherheits-, Abrechnungs- oder Berechtigungslogik zielt, wurde zusätzlich ein `PRIMÄR`-Beleg im Code gesucht; ist keiner vorhanden, ist die Anforderung als `[HYPOTHESE]` gekennzeichnet.
---
## 1. Systemzweck und Stakeholder
### 1.1 Identifizierte Stakeholder-Rollen
| Rolle | Herleitung aus Artefakten |
|---|---|
| **Innendienst / Sachbearbeiter Vertrieb** | Belegrechte `UserRightsConst.Sales.Customer.CustomerCommon.Offer/Order/Invoice/...`, Feld `OfficeStaffI3D` ("Adviser1") an Belegen |
| **Außendienst / Vertriebsmitarbeiter** | Feld `SalesRepresentativeI3D` ("Adviser2"), `UserRightsConst.Sales.Provision.*` |
| **Servicetechniker / Ticketbearbeiter** | `UserRightsConst.Sales.Customer.Helpdesk.*`, `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL` |
| **Lagerist / Logistik** | `UserRightsConst.Logistic.*`, `UserRightsConst.Purchase.StockList.*`, `OrderCommissionBL`, `InventoryBL` |
| **Einkäufer** | `UserRightsConst.Purchase.Supplier.*`, `SupplierEdiBL` |
| **Buchhaltung / Controlling** | `UserRightsConst.Controlling.Finances.*`, `BookKeepingExportBL`, `DunningBL` |
| **Systemadministrator (Anwenderseite)** | `UserRightsConst.Administration.*`, Modul `RightsManagamentAppModuleController`, `SettingsAppModuleController` |
| **Datenschutzbeauftragter** | `UserRightsConst.DsgvoModule.*`, `DataSecurityBL` |
| **Endkunde des Anwenders (Web-Account)** | `WebAccount`-Entität, `WebAccountRightsConst`, `src/nexus/CentronNexus/ServiceBoard`, `WebCart` |
| **Lieferant / Distributor** | EDI-Konfigurationen `SupplierEdiConfigurations`, `src/apis/*` |
| **Hersteller/Betreiber (NEXOWARE Systems GmbH)** | `Directory.Build.props` (`<Company>`), Lizenzserver-Anbindung `LicenseManager`, `LicenseGuids.CentronInternal` |
---
## 2. Stakeholder-Anforderungen
```
ID: StRS-001
Titel: Integriertes ERP-Kernsystem für IT-Systemhäuser
Ebene: StRS
Typ: funktional
Akteur: Anwenderunternehmen (IT-Systemhaus / MSP)
Vorbedingung: Das Unternehmen betreibt Vertrieb, Einkauf, Lager, Service und Abrechnung in einem gemeinsamen Datenbestand.
Fakt: Die Solution `Centron.sln` bündelt 44 Projekte; die Modulregistrierung `ModuleRegistration.cs` gliedert die Anwendung in 15 Modulgruppen (Abrechnung, Administration, Adressen/CRM, Automatisierung, Buchhaltung/Finanzen, Controlling/Analytics, Einkauf, Helpdesk, Hilfe, Logistik, MyCentron, Passwort Manager, Produktion, Stammdaten, Verträge) mit insgesamt 84 registrierten Modul-Controllern.
Aussage: Das System soll die Geschäftsprozesse Vertrieb, Einkauf, Lager/Logistik, Service/Helpdesk, Vertrags- und Abrechnungsmanagement, Buchhaltungsanbindung sowie Controlling in einem integrierten Datenmodell abbilden.
Ergebnis: Ein Anwender kann sämtliche genannten Prozesse ohne Systemwechsel und ohne Datenexport zwischen Fachbereichen ausführen.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:418-905 (`#region c-entron Module: …`, 84× `ModuleRegistrationItem.For<…>`) - Begründung: Die Modulliste ist die im Code durchgesetzte Definition des Funktionsumfangs der Client-Anwendung; sie wird zur Laufzeit ausgewertet und bestimmt, welche Module überhaupt existieren.
- [PRIMÄR] src/backend/Centron.BL/ (Domänenordner: Sales, Warehousing, Administration, CustomerArea, Accounts, EDI, Statistics, Finances, …) - Begründung: Die Ordnerstruktur der Geschäftslogik spiegelt dieselben Domänen wider und belegt, dass die Fachlogik gemeinsam in einer Assembly und gegen eine Datenbank arbeitet.
- [KONTEXT] docs/getting-started/ai-codebase-navigation.md:14-29 (Top-level layout) - Begründung: Bestätigt die Zuordnung der Projektbereiche zu fachlichen Rollen.
Prüfidee: Für jede der 15 Modulgruppen ist mindestens ein registrierter Modul-Controller nachweisbar und über die Oberfläche erreichbar, sofern Recht und Lizenz vorliegen.
Tracelinks: SyRS-015, SyRS-031, SyRS-032, SyRS-033; SwRS-001, SwRS-036, SwRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Rollenbasierte Zugriffssteuerung über Rechtegruppen
Ebene: StRS
Typ: Sicherheit
Akteur: Systemadministrator (Anwenderseite)
Vorbedingung: Es existieren Benutzerkonten und Rechtegruppen im System.
Fakt: Rechte werden nicht direkt an Benutzer vergeben: `AppRightsBL.GetAllAppRightsFromUser` ermittelt Rechte über `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `Sichmemb` verknüpft Benutzer mit Gruppen, `Sichtrus` Gruppen mit Rechten. `UserRightsConst` definiert über 900 numerische Recht-IDs in einer hierarchischen Klassenstruktur.
Aussage: Das System soll Berechtigungen ausschließlich über die Zuordnung Benutzer → Rechtegruppe → Recht vergeben, sodass Berechtigungen zentral über Gruppen administrierbar sind.
Ergebnis: Ein Benutzer besitzt genau die Vereinigungsmenge der Rechte aller Gruppen, denen er angehört.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:651-664 (`GetAllAppRightsFromUser`, SQL über `Sichtrus`/`Sichmemb`) - Begründung: Dies ist die einzige Auflösungsstelle für Benutzerrechte im Backend; sie zeigt das Datenmodell und die durchgesetzte Auflösungsregel.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:63-87 (`GetRightsFromCurrentUser`: Iteration über `user.Groups` → `group.Rights`) - Begründung: Bestätigt dieselbe Semantik auf Entitätsebene (Vereinigungsmenge über Gruppen).
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (gesamt) - Begründung: Zentrale, hierarchisch gegliederte Definition aller Rechtekonstanten.
- [KONTEXT] docs/guides/development/check-userrights.md:3 ("Rights and groups can be managed in the `Rechteverwaltung` module.") - Begründung: Bestätigt die administrative Sicht auf dasselbe Modell.
Prüfidee: Wird einem Benutzer eine Gruppe entzogen, sind alle ausschließlich über diese Gruppe vermittelten Rechte unmittelbar nach Cache-Ablauf nicht mehr wirksam.
Tracelinks: SyRS-009, SyRS-012, SyRS-013, SyRS-014, SyRS-047; SwRS-002, SwRS-003, SwRS-040
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-003
Titel: Mandanten- und Filialfähigkeit mit Sichtbarkeitseinschränkung
Ebene: StRS
Typ: funktional
Akteur: Anwenderunternehmen mit mehreren Standorten
Vorbedingung: Im System sind mehrere Filialen (`Branch`) und mindestens ein Mandant (`Mandator`) angelegt.
Fakt: Belege tragen `BranchI3D` und `BranchOrigin`; Nummernkreise werden je Filiale geführt (`NumberGroup.BranchI3D`, `NumberGroupBL.CreateNumberGroups(mandantI3D, branchI3D)`). Für nahezu jede Belegart existieren einschränkende Rechte `*_ONLY_OWN_BRANCH` (z. B. `SHOW_OFFERS_ONLY_OWN_BRANCH = 20400150`, `EDIT_INVOICE_ONLY_OWN_BRANCH = 20800031`, `CREATE_NEW_ORDER_ONLY_OWN_BRANCH = 20400212`), die in `ReceiptBL.CanUserCreateReceiptsInBranch` und `ReceiptBL.CanUserEditReceipt` gegen `appUser.Employee.BranchI3D` geprüft werden.
Aussage: Das System soll Daten filialbezogen führen und die Sichtbarkeit sowie Bearbeitbarkeit von Belegen, Tickets, Statistiken und Rechtegruppen auf die Filiale des Benutzers einschränken können.
Ergebnis: Ein Benutzer mit einschränkendem Filialrecht sieht und bearbeitet ausschließlich Datensätze der eigenen Filiale; Datensätze der Standardfiliale gelten dabei als eigene Filiale, wenn auch der Benutzer der Standardfiliale zugeordnet ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10270 (`CanUserCreateReceiptsInBranch`) - Begründung: Setzt die Filialbeschränkung beim Neuanlegen durch, inkl. der Sonderregel für die Standardfiliale (`userBranchIsDefaultBranch && receiptBranchIsDefaultBranch`).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295 (`CanUserEditReceipt`, `BranchBL.IsBranchEqual`) - Begründung: Setzt dieselbe Beschränkung beim Bearbeiten durch.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48 und 355-357 (`MANAGE_RIGHTS_ONLY_OWN_BRANCH`) - Begründung: Zeigt, dass die Filialbeschränkung auch die Rechteverwaltung selbst umfasst.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152 (`RefreshAllNumberGroups`, Nummernkreis je Filiale) - Begründung: Belegt filialbezogene Nummernkreise.
- [SEKUNDÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs (`Branch`-Lizenz) - Begründung: Filialfähigkeit ist ein separat lizenziertes Merkmal.
Prüfidee: Ein Benutzer der Filiale A mit Recht `SHOW_INVOICES_ONLY_OWN_BRANCH` erhält beim Öffnen einer Rechnung der Filiale B eine Rechtefehlermeldung.
Tracelinks: SyRS-013, SyRS-018; SwRS-002, SwRS-004
Konsolidierung: Kandidat: Die Filialprüfung ist je Belegart über eigene Recht-IDs und über `IReceiptSpecificLogic.HasRightToEditReceiptOnlyOwnBranch` dupliziert; im Zielsystem als ein generischer Scope-Filter zusammenführbar (vgl. SyRS-006).
Status: belegt
```
```
ID: StRS-004
Titel: Lizenzbasierte Freischaltung von Anwendungen und Einzelfunktionen
Ebene: StRS
Typ: funktional
Akteur: Hersteller (NEXOWARE Systems GmbH) / Anwenderunternehmen
Vorbedingung: Der Web-Service hat eine gültige Lizenzdatei vom Lizenzserver bezogen oder aus dem lokalen Cache geladen.
Fakt: `LicenseGuids.cs` definiert 159 Lizenz-GUIDs. `ApplicationKind.cs` definiert 44 anmeldefähige Anwendungen, jeweils mit `LicenseGuid`, optionalen `AdditionalLicenseGuids`, `ExpirationKind`, `LicenseUsageKind` sowie optional `RequiredRight`/`DisallowingRight`. `LicenseManager.CheckLicense` prüft Version (`CheckLicenseVersion`) und Anzahl gleichzeitig genutzter Lizenzen (`GetLicenseCount` vs. `TicketBL.GetTicketCount`). In `ModuleRegistration.cs` ist jedes Modul mit einer Kombination aus Rechteprüfung UND Lizenzprüfung registriert.
Aussage: Das System soll die Verfügbarkeit von Anwendungen und einzelnen Funktionsmodulen an den Besitz einer Lizenz, deren Gültigkeitsversion und deren Nutzeranzahl koppeln.
Ergebnis: Ohne passende Lizenz ist ein Modul in der Oberfläche nicht sichtbar; ohne gültige Anwendungslizenz schlägt die Anmeldung mit einer lizenzbezogenen Fehlermeldung fehl.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302 (`CheckLicense`, `DefaultMessageCodes.LicenseMaximumReached`) - Begründung: Durchgesetzte Prüfung von Lizenzbesitz, Version und Nutzungsanzahl vor Ticketerzeugung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:131-139 (`LicenseManager.CheckLicense(...)` im Anmeldepfad) - Begründung: Zeigt, dass die Anmeldung ohne erfolgreiche Lizenzprüfung abgebrochen wird.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:421-448 u. a. (`ModuleRegistrationItem.For<T>(rechteLambda, lizenzLambda)`) - Begründung: Modulsichtbarkeit ist im Code hart an `LicenseManager.Instance.HasLicense(...)` gebunden.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:10-53 - Begründung: Definiert die anmeldefähigen Anwendungen und ihre Lizenzkopplung.
- [KONTEXT] docs/reference/security/licensing-system.md:3-31 - Begründung: Beschreibt Lizenzmodell (GUID, count, valid until date, valid until version) fachlich.
Prüfidee: Entzieht man die Lizenz `LicenseGuids.PasswordManager`, ist das Modul „Passwort Manager" nach Neustart des Clients nicht mehr in der Modulliste enthalten, obwohl die Rechte unverändert sind.
Tracelinks: SyRS-006, SyRS-007, SyRS-008, SyRS-015; SwRS-005
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Durchgängige Belegkette vom Angebot bis zur Rechnung
Ebene: StRS
Typ: funktional
Akteur: Innendienst / Sachbearbeiter Vertrieb
Vorbedingung: Ein Kunde ist im Adressstamm angelegt und nicht gesperrt.
Fakt: `CentronObjectKindNumericExtensions.IsCustomerReceipt` definiert genau sieben Kundenbelegarten: Angebot (1), Auftrag (2), Lieferschein (3), Rechnung (4), Abholschein (5), Gutschrift (6), Vertrag (22). Alle erben von `ReceiptBase` mit gemeinsamen Feldern Number/Date/Version/State. `ReceiptWebServiceBL.ForwardReceipt(...)` erzeugt Folgebelege aus Ursprungsbelegen; `IReceiptItemWithOrigin` (Felder `OriginKind`, Herkunftsverweis) hält die Herkunft je Position fest; `ReceiptBL.GetReceiptForwardedInto(...)` ermittelt, in welche Folgebelege ein Beleg weiterverarbeitet wurde.
Aussage: Das System soll die Belegarten Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift und Vertrag als Kundenbelege führen und die Weiterverarbeitung eines Belegs in einen Folgebeleg positionsgenau nachvollziehbar machen.
Ergebnis: Zu jeder Belegposition ist die Ursprungsposition und zu jedem Beleg die Menge der daraus erzeugten Folgebelege ermittelbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:273-287 (`IsCustomerReceipt`) - Begründung: Abschließende, im Code durchgesetzte Aufzählung der Kundenbelegarten.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72 - Begründung: Gemeinsame Belegkopf-Struktur aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3111-3114 (`GetReceiptForwardedInto(...)` blockiert neue Versionen bei bereits weiterverarbeiteten Belegen) - Begründung: Beweist, dass Weiterverarbeitungsbeziehungen persistiert und geschäftsregelrelevant sind.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1815-1841 (`receiptBL.ForwardReceipt(CentronObjectKindNumeric.InvoiceClass, …, originReceipts: [ReceiptKind = ContractClass])`) - Begründung: Konkreter Nachweis der Belegkettenbildung Vertrag → Rechnung.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:37-45 (Tabelle Belegart/Entität/Tabelle/View) - Begründung: Ordnet den Belegarten die persistierenden Strukturen zu.
Prüfidee: Wird aus einem Auftrag ein Lieferschein erzeugt, liefert `GetReceiptForwardedInto` für den Auftrag den Lieferschein; die Lieferscheinposition trägt `OriginKind = OrderClass`.
Tracelinks: SyRS-016, SyRS-017, SyRS-018, SyRS-019, SyRS-020, SyRS-022, SyRS-023; SwRS-006, SwRS-007, SwRS-009, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Vertragsverwaltung mit wiederkehrender, automatisierter Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung / Vertragsverwaltung
Vorbedingung: Ein Vertrag (Belegart `ContractClass`) ist angelegt und aktiv.
Fakt: `BillingIntervalKinds` definiert `Daily=0`, `Monthly=1`, `Yearly=2`, `Quarterly=3`; `BillingKinds` definiert `Billingadvance=0` („vorschüssig") und `Billingarrear=1` („nachschüssig"); `ContractCalculationKind` ist ein `[Flags]`-Enum mit `None=0`, `Auto=1` („automatische Abrechnung"), `Need=2` („Abrechnung nach Bedarf"), `Manual=4` („manuell Abrechnung"). `AutomaticFacturaWebServiceBL.CreateInvoiceToContractComplete` erzeugt aus Verträgen Rechnungen. Der Hintergrunddienst `ContractEndeService` und `ContractCloseService` laufen im Web-Service-Host.
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall (Tag, Monat, Quartal, Jahr), Intervalldauer sowie vor- oder nachschüssiger Abrechnungsweise führen und daraus automatisch, bedarfsgesteuert oder manuell Rechnungen erzeugen.
Ergebnis: Für einen fälligen Vertrag entsteht eine Rechnung, deren Positionen aus den vertragsrelevanten Vertragspositionen abgeleitet sind und deren Abrechnungszeitraum dem konfigurierten Intervall entspricht.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs - Begründung: Abschließende Aufzählung der zulässigen Abrechnungsintervalle mit deutschsprachigen Anzeigetexten.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingKind.cs - Begründung: Definiert vor-/nachschüssige Abrechnung als Geschäftsregel.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/ContractCalculationKind.cs - Begründung: Definiert die Auslösearten der Abrechnung.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1699-1841 (`CreateInvoiceToContractComplete`) - Begründung: Implementiert die Rechnungserzeugung aus Verträgen einschließlich Zählerdaten und Staffelpreisen.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ContractEndeService.cs, ContractCloseService.cs - Begründung: Belegt automatisierte, zeitgesteuerte Vertragsverarbeitung im Serverbetrieb.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:42-95 - Begründung: Beschreibt die Vertragsattribute fachlich (Kontingent, Prolongation, Monitoring).
Prüfidee: Ein Vertrag mit `BillingIntervalKind = Monthly`, `BillingIntervalDuration = 3`, `BillingKind = Billingadvance` erzeugt zu Quartalsbeginn genau eine Rechnung über den kommenden Dreimonatszeitraum.
Tracelinks: SyRS-023, SyRS-029; SwRS-009, SwRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Ticket-/Helpdesk-Management mit abrechenbarer Zeiterfassung
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker / Ticketbearbeiter
Vorbedingung: Der Benutzer besitzt das Recht `SHOW_HELPDESK`; ein Kunde ist zugeordnet.
Fakt: Der Objekttyp `HelpdeskClass = 10` und `HelpdeskTimerClass = 4000056` sind eigenständige Objektarten. `HelpdeskBL`, `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL`, `HelpdeskTimerArticleBookingBL` und `ReceiptItemTimerBL` (104 KB) verbinden Ticketzeiten mit Belegpositionen. `UserRightsConst.Sales.Customer.Helpdesk` enthält 26 Rechte, u. a. `EDIT_TIME`, `OWN_TIME_EDIT`, `MOVE_HELPDESK_TIMER`, `DELETE_HELPDESK_TIMER`, `SHOW_ALL_EMPLOYEE_TIMES`. Das Modul `TimerBillingAppModuleController` („Vereinfachte Ticketabrechnung") ist an das Recht `TIMER_BILLING_MODULE` und die Lizenz `SimplifiedTicketBilling` gebunden.
Aussage: Das System soll Serviceanfragen als Tickets führen, geleistete Zeiten je Ticket und Mitarbeiter erfassen und diese Zeiten als Positionen in Kundenbelege überführen können.
Ergebnis: Eine erfasste Ticketzeit ist eindeutig einem Ticket, einem Mitarbeiterartikel und – nach Abrechnung – einer Belegposition zugeordnet und kann danach nicht mehr frei verschoben oder gelöscht werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemTimerBL.cs - Begründung: Implementiert die Verbindung Ticketzeit ↔ Belegposition (`FillReceiptWithTimerI3Ds`, aufgerufen in `ReceiptBL`).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3691 (`UpdateArticlePositionsHelpdeskTimerI3Ds(receipt)`) - Begründung: Beim Belegspeichern werden Ticketzeit-Referenzen an Positionen fortgeschrieben.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1952-2015 (Helpdesk-Rechteblock) - Begründung: Definiert die durchgesetzten Rechte rund um Ticketzeiten.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:441-443 (Modul „Vereinfachte Ticketabrechnung") - Begründung: Belegt die Abrechnung von Ticketzeiten als eigenständige, lizenzierte Fachfunktion.
- [KONTEXT] CentronRights.md:59-66 („Helpdeskzeiten verschieben … aber nur, wenn das Ticket nicht Teil eines Belegs ist") - Begründung: Fachliche Formulierung der Sperrregel nach Abrechnung.
Prüfidee: Eine Ticketzeit, die in einer Rechnung abgerechnet wurde, lässt sich auch mit Recht `MOVE_HELPDESK_TIMER` nicht mehr auf ein anderes Ticket verschieben.
Tracelinks: SyRS-013, SyRS-026, SyRS-027; SwRS-011, SwRS-012, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Lagerbestandsführung mit Serien-/Barcodeverfolgung
Ebene: StRS
Typ: funktional
Akteur: Lagerist / Logistik
Vorbedingung: Ein Artikel ist im Artikelstamm angelegt und einem Lager zugeordnet.
Fakt: `ReceiptArticleBookingBL.BookArticles`/`UnBookArticles` verändern Lagerbestände beim Speichern von Belegen; `ValidateArticleWarehouses` prüft die Lagerzuordnung der Positionen. Artikel besitzen das Merkmal `NeedsBarcodes`; `ReceiptBarcodeBL` (98 KB) prüft `CheckBarcodeCountsInTheReceipt`, `CheckIfAllNonActiveBarcodesAreStillInTheReceipt` und `CheckForDuplicateBarcodes`. Für Seriennummernverwaltung existiert der Rechteblock `UserRightsConst.Purchase.StockList.SerialAdministration` mit 7 Rechten (u. a. `ADD_SERIAL_NUMBER`, `REPLACE_SERIAL_NUMBER`, `RESET_SERIAL_NUMBER`).
Aussage: Das System soll Lagerbestände beleggesteuert fortschreiben und für gekennzeichnete Artikel die Erfassung, Zuordnung und Verfolgung von Seriennummern/Barcodes je Belegposition erzwingen.
Ergebnis: Beim Speichern eines bestandsrelevanten Belegs sind die Lagerbestände konsistent fortgeschrieben; für seriennummernpflichtige Artikel ist die Anzahl erfasster Barcodes gleich der Positionsmenge.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3767-3777 (`CheckBarcodeCountsInTheReceipt`, `ValidateArticleWarehouses` – Abbruch bei Fehler) - Begründung: Speichern wird bei unvollständiger Barcodeerfassung oder ungültigem Lager verweigert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3859-3868 (`UnBookArticles`/`BookArticles`) - Begründung: Bestandsfortschreibung ist Teil des Belegspeicherns, nicht optional.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:347-366 (Bestandsdifferenz, `article.NeedsBarcodes`) - Begründung: Zeigt die konkrete Bestandsberechnung und die Sonderbehandlung barcodegeführter Artikel.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1772-1783 (`SerialAdministration`) - Begründung: Serienummernoperationen sind einzeln rechtegeschützt.
Prüfidee: Ein Lieferschein mit einer Position über 3 Stück eines Artikels mit `NeedsBarcodes = true` und nur 2 erfassten Barcodes lässt sich nicht speichern.
Tracelinks: SyRS-017, SyRS-020, SyRS-025; SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Elektronischer Datenaustausch mit Distributoren (EDI)
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer / Lieferant
Vorbedingung: Für den Lieferanten ist eine EDI-Konfiguration (`SupplierEdiConfigurations`) mit Verbindungsdaten hinterlegt.
Fakt: `SupplierEdiBL` (118 KB) ist als partielle Klasse je Distributor aufgeteilt (`.Also`, `.AlsoCH`, `.Alltron`, `.Herweck`, `.Komsa`, `.Opentrans`). Im Verzeichnis `src/backend/Centron.Gateway/` existieren eigenständige Parser-Bibliotheken `EDI_Alltron`, `EDI_Also`, `EDI_AlsoCH`, `EDI_EGIS`, `EDI_Herweck`, `EDI_Komsa`, `OpenTrans`, `OpenTrans1_0`, `ZUGFeRD21_Extended`. Der Hintergrunddienst `EdiDownloadService` ruft EDI-Dateien zyklisch ab.
Aussage: Das System soll Bestellungen elektronisch an Distributoren übermitteln sowie Auftragsbestätigungen, Lieferavise und Rechnungen der Distributoren automatisiert einlesen und den zugehörigen Bestellungen zuordnen.
Ergebnis: Eingelesene EDI-Dokumente aktualisieren die zugehörigen Lieferantenbelege (Mengen, Preise, Termine, Seriennummern) und werden protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs und Partialklassen im selben Verzeichnis - Begründung: Enthält die Verarbeitungslogik je Distributorformat.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs - Begründung: Belegt den automatisierten, zyklischen Abruf im Serverbetrieb.
- [PRIMÄR] src/backend/Centron.Gateway/ (Unterverzeichnisse EDI_*, OpenTrans*, ZUGFeRD21_Extended) - Begründung: Eigenständige Formatbibliotheken belegen die unterstützten Standards.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:687 (`EDIManagementController`, Recht `RIGHT_EDIMANAGEMENT = 20400343`) - Begründung: EDI-Verwaltung ist ein eigenes, rechtegeschütztes Modul.
- [KONTEXT] docs/reference/edi/edi-architecture.md:114-122 (Matrix Lieferant × Dokumentart) - Begründung: Dokumentiert, welcher Distributor welche Dokumentarten unterstützt.
Prüfidee: Für jeden in `EdiDataType` gelisteten Formattyp existiert eine Leseroutine, die eine Beispieldatei in c-entron-Belegdaten überführt.
Tracelinks: SyRS-034, SyRS-035; SwRS-024
Konsolidierung: Kandidat: Die Verarbeitungspfade je Distributor duplizieren Kopf-/Positions-Mapping; im Zielsystem als ein Mapping-Framework mit formatspezifischen Adaptern zusammenführbar.
Status: belegt
```
```
ID: StRS-010
Titel: Finanzprozesse: Offene Posten, Mahnwesen, Zahlungsverkehr, Buchhaltungsexport
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung
Vorbedingung: Es existieren gebuchte Rechnungen und ein konfiguriertes Kontenrahmen-/Buchhaltungssystem.
Fakt: Es existieren die Module `DunningOverviewAppModuleController`, `OposOverviewAppModuleController`, `PaymentTransactionAppModuleController`, `PaymentsAppModuleController`, `OutgoingPaymentsAppModuleController`, `DatevOnlineAppModuleController`, `AccountSystemsAppModuleController`. `DunningLevel` definiert `None`, `Level1`, `Level2`, `Level3`. `BookKeepingExportBL` (81 KB) implementiert den Buchhaltungsexport. `UserRightsConst.Controlling.Finances` enthält u. a. `Dunning = 10971`, `INCOMING_PAYMENT_TRANSACTIONS = 10980`, `OUTGOING_PAYMENT_TRANSACTIONS = 10981` und den Unterblock `OnlineBanking`.
Aussage: Das System soll offene Posten verwalten, ein dreistufiges Mahnwesen betreiben, Zahlungsein- und -ausgänge verarbeiten und Buchungsdaten an ein externes Finanzbuchhaltungssystem exportieren.
Ergebnis: Zu jedem Kunden ist eine aktuelle Mahnstufe ermittelbar; Buchungsdaten sind in einem für die Finanzbuchhaltung lesbaren Format exportierbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs - Begründung: Definiert die dreistufige Mahnskala als Typ.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs, DunningRunBL.cs - Begründung: Implementieren Mahnlaufermittlung und -durchführung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs - Begründung: Implementiert den Buchhaltungsexport.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10228-10249 (`GetCustomerOrSupplierDunningLevel`, Rückgabe 0..3) - Begründung: Bestätigt die dreistufige Skala als geschäftswirksame Größe.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:596-626 (Modulgruppe „Buchhaltung/Finanzen") - Begründung: Zeigt die fachliche Gliederung der Finanzfunktionen.
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/ - Begründung: Belegt die Anbindung eines externen Bankschnittstellenanbieters für Kontoumsätze.
Prüfidee: Für einen Kunden mit überfälliger Rechnung nach Mahnlauf ist `DunningLevel` ≥ 1 und im Modul „Mahnwesen" sichtbar.
Tracelinks: SyRS-024, SyRS-034; SwRS-013, SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Selbstbedienungsportal für Endkunden des Anwenders
Ebene: StRS
Typ: funktional
Akteur: Endkunde des Anwenders (Web-Account)
Vorbedingung: Für einen Ansprechpartner eines aktiven, nicht gesperrten Kunden ist ein Web-Account mit `Status = 1` angelegt.
Fakt: `src/nexus/CentronNexus` ist eine Blazor-Server-Anwendung mit den Bereichen `ServiceBoard` (341 Dateien), `WebCart` (46), `WebOffer` (6), `DocumentSigning` (2), `ProductionOrderManagement` (4), `Office`, `Settings`, `Management`. `WebAccountBL.LoginWithWebAccount` authentifiziert Web-Accounts; `WebAccountRightsConst` definiert Web-Rechte (z. B. `WEBRIGHT_CREATEREQUEST`, `WEBRIGHT_EDITALLREQUESTS`). `ApplicationKind.ServiceBoardOnline` und `ApplicationKind.WebCart` sind eigene lizenzierte Anwendungen.
Aussage: Das System soll Endkunden des Anwenders über ein Webportal ermöglichen, Tickets zu erstellen und zu verfolgen, Artikel aus ihren Sonderpreisen zu bestellen sowie Dokumente einzusehen und zu signieren.
Ergebnis: Ein authentifizierter Web-Account sieht ausschließlich die Daten des ihm zugeordneten Kunden und nur die über Web-Rechte freigegebenen Funktionen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:54-95 (`LoginWithWebAccount`: `Status == 1`, Prüfung Ansprechpartner/Anschrift/Kunde aktiv und nicht gesperrt) - Begründung: Durchgesetzte Zugangsregel des Portals.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-415, 468-479 (`CheckWebRights`, `WebAccountRightsConst.WEBRIGHT_CREATEREQUEST`) - Begründung: Web-Accounts unterliegen einem eigenen, getrennten Rechtemodell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (`CanUserViewReceipt`: „Web-Benutzer haben keine Berechtigung Belege einzusehen.") - Begründung: Belegt die harte Abgrenzung des Portalzugriffs gegenüber dem internen Belegwesen.
- [SEKUNDÄR] README.md:31-36 (WebCart-Beschreibung: „available if you login as a web-account", Artikel aus „Sonderpreise") - Begründung: Beschreibt die fachliche Nutzungsabsicht des WebCart.
- [SEKUNDÄR] src/nexus/CentronNexus.Host/appsettings.json (`Branding.Title = "NEXOWARE ServiceBoard"`, `LoginPageText = "Ihr cleveres Ticketsystem"`) - Begründung: Portalzweck aus der Auslieferungskonfiguration.
Prüfidee: Ein Web-Account, dessen zugeordneter Kunde gesperrt wird, kann sich nicht mehr am Portal anmelden.
Tracelinks: SyRS-006, SyRS-026, SyRS-037, SyRS-038; SwRS-040
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Gesetzeskonforme elektronische Rechnungsstellung (ZUGFeRD/XRechnung)
Ebene: StRS
Typ: Sicherheit
Akteur: Buchhaltung / Rechnungsempfänger (auch öffentliche Auftraggeber)
Vorbedingung: Die Einstellung `ApplicationSettingID.IsZugferdInvoiceActive` ist aktiviert; für den Empfänger ist ggf. eine Leitweg-ID hinterlegt.
Fakt: `InvoiceZugferdBL` erzeugt XML nach `ZugferdKind` (`ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2`, `_2_0`, `_2_2`, `_2_3_1`, `_3_0_1`). Bei gesetzter `leitwegID` wird `ZugferdFileKind.XInvoice` und die PDF-Konformitätsstufe `PdfZugferdConformanceLevel.XRechnung` verwendet, sonst `Comfort`/`EN16931`. Die XML-Datei wird als `factur-x.xml` (bzw. `ZUGFeRD-invoice.xml` für Version 1.0) in das PDF eingebettet (`AttachZugferdInvoice`). Beim Export wird die UTF-8-BOM entfernt (`stream.ToArray().Skip(3)`).
Aussage: Das System soll Ausgangsrechnungen zusätzlich zum PDF als strukturierten elektronischen Rechnungsdatensatz erzeugen, dabei die konfigurierte ZUGFeRD-/XRechnung-Version verwenden und bei Vorliegen einer Leitweg-ID das XRechnung-Profil anwenden.
Ergebnis: Die erzeugte Rechnungsdatei ist ein PDF/A-3 mit eingebettetem `factur-x.xml` in der konfigurierten Profilstufe; ohne BOM und mit korrekt gesetzter Konformitätsstufe.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:147-165 (`GenerateZugferdFile`, BOM-Entfernung) - Begründung: Erzeugt den strukturierten Datensatz und setzt die Formatregel technisch durch.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:193-212 (`PdfZugferdConformanceLevel.EN16931` vs. `.XRechnung`, `AttachZugferdInvoice`) - Begründung: Belegt die leitweg-abhängige Profilwahl und die PDF-Einbettung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 (`IsZugferdEnabled` über `ApplicationSettingID.IsZugferdInvoiceActive`) - Begründung: Zeigt die Konfigurierbarkeit als Systemeinstellung.
- [SEKUNDÄR] docs/reference/zugferd-feldzuordnung-anwender.md, docs/reference/zugferd-field-mapping.md - Begründung: Feldzuordnung zwischen c-entron-Daten und ZUGFeRD-Elementen.
- [KONTEXT] docs/guides/development/xrechnung.md:3-4 (Verweis auf ZUGFeRD-2.1.1-Spezifikation) - Begründung: Bestätigt den zugrunde gelegten Standard.
- [KONTEXT] Commit `7d62212022` „Fix: Correct discount calculation to retain sign for ZUGFeRD total check integrity" - Begründung: Belegt, dass Summenkonsistenzprüfungen des Standards praxisrelevant sind.
Prüfidee: Eine mit Leitweg-ID erzeugte Rechnung besteht die Validierung des KOSIT-XRechnung-Prüftools; ohne Leitweg-ID entsteht ein EN16931-konformes ZUGFeRD-PDF.
Tracelinks: SyRS-030; SwRS-015
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Umsetzung des Löschanspruchs nach DSGVO
Ebene: StRS
Typ: Sicherheit
Akteur: Datenschutzbeauftragter
Vorbedingung: Der Benutzer besitzt das Recht `UserRightsConst.DsgvoModule.DSGVO_DELETE_CONTACT`; das Modul ist lizenziert.
Fakt: `DataSecurityBL.DsgvoDeleteRightDeleteContacts` prüft zunächst `currentUser.HasUserRight(UserRightsConst.DsgvoModule.DSGVO_DELETE_CONTACT)`. Die Löschung erfolgt als Anonymisierung: personenbezogene Felder (Name, Telefon, Fax, E-Mail 1/2, Freitexte, Abteilung, Bild, Active-Directory-SID, Webseite, Web-Benutzername/-Kennwort, Titel) werden auf `null` gesetzt, `Kommentar` wird auf „DSGVO: Auf Anfrage gelöscht. (Durchgeführt von {0} am {1:d} um {1:t} Uhr)" gesetzt und die Felder `IsDsgvoDeleted = true`, `DsgvoDeletedEmployeeI3D`, `DsgvoDeletedDate` werden gefüllt. Jeder gelöschte Feldwert wird zuvor in ein Löschprotokoll geschrieben (`DoAppendDeleteProtocol`).
Aussage: Das System soll auf Antrag einer betroffenen Person deren personenbezogene Daten anonymisieren, den Vorgang mit ausführendem Mitarbeiter und Zeitpunkt kennzeichnen und ein Protokoll der entfernten Werte erzeugen.
Ergebnis: Nach der Verarbeitung enthält der Datensatz keine personenbezogenen Klartextdaten mehr, ist als DSGVO-gelöscht markiert und der Vorgang ist über das Löschprotokoll nachweisbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:787-789 (Rechteprüfung `DSGVO_DELETE_CONTACT`) - Begründung: Durchgesetzte Zugriffsbeschränkung der Löschfunktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1195-1275 (Feldweise Anonymisierung, `IsDsgvoDeleted`, `DsgvoDeletedEmployeeI3D`, `DsgvoDeletedDate`, `DoAppendDeleteProtocol`) - Begründung: Zeigt Umfang und Nachweisführung der Anonymisierung im Detail.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 (Konstanten `DsgvoDeletedContactMessage`) - Begründung: Standardisierter Kennzeichnungstext.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:460-462 (Modul „c-entron DSGVO", Recht `ACCESS_DSGVO_MODULE`, Lizenz `CentronDSGVO`) - Begründung: DSGVO-Funktionen sind ein eigenes, rechte- und lizenzgeschütztes Modul.
Prüfidee: Nach DSGVO-Löschung eines Ansprechpartners enthält der Datensatz in allen personenbezogenen Feldern `NULL` oder den Standardtext; das Löschprotokoll listet jeden zuvor belegten Feldwert.
Tracelinks: SyRS-028; SwRS-016
Konsolidierung: Kandidat: Die Anonymisierungslogik ist in `DataSecurityBL` für mindestens drei Datenmodelle (Kunden-Ansprechpartner, Accounts-Ansprechpartner, Kreditoren-Ansprechpartner) getrennt implementiert; im Zielsystem zu einer generischen, deklarativ konfigurierten Anonymisierung zusammenführbar.
Status: belegt
```
```
ID: StRS-014
Titel: Nachvollziehbarkeit von Änderungen (Belegversionierung und Änderungsprotokolle)
Ebene: StRS
Typ: nicht-funktional
Akteur: Anwenderunternehmen / Wirtschaftsprüfung
Vorbedingung: Ein Beleg oder ein protokollierter Stammdatensatz wird geändert.
Fakt: Jeder Beleg trägt `Version`; `ReceiptBL.CreateNewVersion` setzt `receipt.Version = currentReceiptVersion.Version + 1`, und `SaveReceipt` akzeptiert ausschließlich `Version == 1` (Erstversion), `== previousVersion.Version` oder `== previousVersion.Version + 1` – andernfalls „Der Beleg hat keine gültige Versionsnummer.". Alte Versionen werden in eigene Versionstabellen (`*KopfVersions`/`*PosVersions`) kopiert. Zusätzlich schreibt der NHibernate-Listener `ChangeTrackingEventListener` (`IPreUpdateEventListener`) für attributierte Entitäten je geändertem Feld einen `ChangeLog`-Eintrag mit `ObjectI3D`, `ObjectKind`, `Property`, `OldValue`, `NewValue`, `Date`, `AppUser`. Rechteänderungen werden separat in `AppRightLog` protokolliert.
Aussage: Das System soll Änderungen an Belegen versionsbasiert und Änderungen an gekennzeichneten Stammdatenfeldern feldgenau mit Benutzer und Zeitpunkt protokollieren, sodass jeder Stand rekonstruierbar bleibt.
Ergebnis: Zu jedem Beleg existiert eine lückenlose Versionshistorie; zu jedem protokollierten Feld existiert ein Änderungseintrag mit Alt-/Neuwert, Zeitpunkt und Benutzer.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578 (Versionsnummernvalidierung mit Fehlermeldung) - Begründung: Erzwingt eine lückenlose Versionsfolge.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3117 (`receipt.Version = currentReceiptVersion.Version + 1`) und 3621-3634 (`SaveReceiptVersion(receipt, previousReceiptVersion)`) - Begründung: Zeigt Erzeugung und Wegschreiben der Vorgängerversion.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-142 - Begründung: Implementiert das feldgenaue Änderungsprotokoll als ORM-Interceptor, also unabhängig vom aufrufenden Anwendungsfall.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-857 (`AppRightLog`, Kinds `AddRightToGroup`, `RemoveRightFromGroup`, `AddUserToGroup`, …) - Begründung: Separates Protokoll für sicherheitsrelevante Rechteänderungen.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 (Versionstabellen als 1:1-Kopien) - Begründung: Erläutert die Persistenzstrategie der Versionierung.
Prüfidee: Nach dreimaliger Änderung eines Angebots existieren in `AngKopfVersions` zwei Vorgängerversionen mit fortlaufenden Versionsnummern und der aktuelle Beleg trägt `Version = 3`.
Tracelinks: SyRS-016, SyRS-017, SyRS-036, SyRS-046, SyRS-047; SwRS-008, SwRS-017, SwRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Kreditlimit- und Mahnstufensteuerung im Vertriebsprozess
Ebene: StRS
Typ: funktional
Akteur: Innendienst / Kreditmanagement
Vorbedingung: Für den Kunden ist ein Kreditlimit (`CreditLimit`) und eine Berechnungsart (`CreditLimitCalculationKind`) hinterlegt.
Fakt: `ReceiptBL.CheckIfCustomerLimitIsReached` summiert über alle limitrelevanten Belegarten das verbrauchte Limit, zieht das Limit der Vorgängerversion ab und meldet bei Überschreitung `ShowCustomerLimitExceededDialog` mit einer Meldung, die Limit, Überschreitungsbetrag und Verbrauch je Belegart nennt; gespeichert wird nur bei `data.SaveAlthoughCustomerLimitExceeded == true`. Die Berechnung erfolgt netto (`CreditLimitCalculationKind == 1`) oder brutto; bei `CreditLimitCalculationKind == null || == 2 || CreditLimit <= 0` findet keine Prüfung statt. Unabhängig davon blockiert `CanUserCreateNewReceiptsAtCustomerOrSupplier` das Anlegen neuer Belege, wenn die Mahnstufe des Kunden die belegartspezifische Sperrstufe erreicht; das Recht `IGNORE_DUNNING_BLOCKING_FOR_RECEIPTS = 20400085` hebt dies auf.
Aussage: Das System soll vor dem Speichern eines limitrelevanten Kundenbelegs prüfen, ob das Kreditlimit des Kunden überschritten wird, und den Vorgang nur nach ausdrücklicher Bestätigung fortsetzen; bei erreichter Mahnstufe soll das Anlegen neuer Belege gesperrt werden.
Ergebnis: Bei Limitüberschreitung erscheint eine Rückfrage mit beziffertem Überschreitungsbetrag; bei erreichter Sperr-Mahnstufe wird das Anlegen mit belegartbezogener Meldung abgelehnt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:8636-8690 (`CheckIfCustomerLimitIsReached`) - Begründung: Vollständige, durchgesetzte Limitregel inkl. Netto/Brutto-Unterscheidung und Ausnahmebedingungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10205-10216 (Mahnstufensperre, `BlockNewReceiptsDunningLevel`) - Begründung: Durchgesetzte Sperrregel bei Mahnstufe.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2157-2161 (`IGNORE_DUNNING_BLOCKING_FOR_RECEIPTS` mit deutschsprachiger Rechtebeschreibung) - Begründung: Beschreibt die Ausnahmeberechtigung fachlich.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2404 (`EDIT_LIMIT_CUSTOMER`) - Begründung: Die Limitpflege ist eigenständig rechtegeschützt.
Prüfidee: Ein Auftrag, der das Restlimit eines Kunden um 100 EUR überschreitet, führt zu einer Rückfrage, deren Text den Betrag 100,00 und den Verbrauch je Belegart ausweist; ohne Bestätigung wird nicht gespeichert.
Tracelinks: SyRS-017, SyRS-021; SwRS-013, SwRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Provisionsermittlung für Vertriebsmitarbeiter
Ebene: StRS
Typ: funktional
Akteur: Außendienst / Vertriebsleitung
Vorbedingung: Ein Provisionsschema ist angelegt und einem Kunden zugeordnet.
Fakt: Es existieren die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`, `ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionItemEntity`, `ReceiptProvisionEmployeeGoal`, `ReceiptProvisionEmployeeLevel` sowie `ReceiptProvisionBL` (45 KB) und `ReceiptProvisionSchemaBL` (29 KB). `ReceiptBL` ruft beim Laden `_receiptProvisionBL.FillReceiptWithProvision(receipt)` auf. Der Rechteblock `UserRightsConst.Sales.Provision` umfasst `PROVISION_EVALUATION_MODULE`, `PROVISION_EVALUATION_ONLY_OWN`, `PROVISION_SCHEMA_MANAGEMENT`, `PROVISION_SCHEMA_CUSTOMER_ASSIGNMENT`, `CAN_SEE_ALL_PROVISION_IN_RECEIPTS`, `PROVISION_EVALUATION_ONLY_OWN_BRANCH`. Der Hintergrunddienst `UpdateExpiredProvisionSchemasService` läuft stündlich.
Aussage: Das System soll je Beleg Provisionsbeträge nach kundenbezogen zugeordneten Provisionsschemas ermitteln und die Auswertung wahlweise auf die eigenen Vorgänge bzw. die eigene Filiale beschränken.
Ergebnis: Zu jedem provisionsrelevanten Beleg sind Provisionswerte je Position ermittelt; die Provisionsauswertung zeigt Benutzern ohne erweitertes Recht nur eigene Werte.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptProvisionBL.cs; src/backend/Centron.BL/Sales/Receipts/ReceiptProvisionSchemaBL.cs - Begründung: Implementieren Schemaverwaltung und Provisionsberechnung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7250 (`FillReceiptWithProvision`) - Begründung: Provisionsdaten sind fester Bestandteil des Belegladens.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2443-2453 (Provisionsrechte) - Begründung: Durchgesetzte Sichtbarkeitsabstufung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs:45 (`TimeSpan.FromHours(1)`) - Begründung: Belegt die zeitliche Gültigkeit von Provisionsschemas und deren automatische Fortschreibung.
Prüfidee: Ein Benutzer mit `PROVISION_EVALUATION_ONLY_OWN` sieht in der Provisionsauswertung ausschließlich Belege, bei denen er als Betreuer eingetragen ist.
Tracelinks: SyRS-013; SwRS-020
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: Auswertungen und Kennzahlen für die Unternehmenssteuerung
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung / Controlling
Vorbedingung: Der Benutzer besitzt das jeweilige Statistikrecht.
Fakt: `UserRightsConst.Controlling.Analytics` definiert je Auswertungsart ein eigenes Recht: `SALES_STATISTIC`, `PURCHASE_STATISTIC`, `TICKET_STATISTIC`, `CONTRACT_STATISTIC`, `EMPLOYEE_STATISTIC`, `OFFER_STATISTIC`, `SALE_PURCHASE_ARTICLE_STATISTIC` sowie das einschränkende Recht `SHOW_ONLY_STATISTIC_FROM_OWN_BRANCH = 20800145`. Der Ordner `src/backend/Centron.BL/Statistics` enthält 16 Dateien, `Centron.Entities/Entities/Statistics` 35. Module: `SaleStatisticsAppModuleController`, `EmployeeAnalyticsAppModuleController`, `ManagementInfoAppModuleController`, `ContractEvaluation2AppModuleController`, `MspDashboardAppModuleController`.
Aussage: Das System soll Auswertungen zu Umsatz, Einkauf, Tickets, Verträgen, Mitarbeitern und Angeboten bereitstellen, deren Zugriff je Auswertungsart einzeln berechtigt und optional auf die eigene Filiale beschränkt werden kann.
Ergebnis: Ein Benutzer sieht ausschließlich die Auswertungen, für die er das jeweilige Recht besitzt; mit dem Filialrecht sind die Kennzahlen auf seine Filiale reduziert.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2574-2586 (`Controlling.Analytics`) - Begründung: Je Auswertungsart eigenes, durchgesetztes Recht.
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/README.md:12-19 – Beispiel `[AuthorizeUserRight(UserRightsConst.Controlling.Analytics.SALES_STATISTIC)]` - Begründung: Zeigt die Durchsetzung des Statistikrechts auch an der modernen REST-Schnittstelle.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:628-670 (Modulgruppe „Controlling/Analytics") - Begründung: Bestätigt die Auswertungen als eigenständige Fachmodule.
Prüfidee: Ein Benutzer ohne `TICKET_STATISTIC` erhält beim Aufruf der Ticketstatistik über die REST-Schnittstelle HTTP 403.
Tracelinks: SyRS-009, SyRS-013; SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Deutschsprachige Anwenderoberfläche mit optionaler englischer Sprachfassung
Ebene: StRS
Typ: nicht-funktional
Akteur: Endanwender
Vorbedingung: –
Fakt: Die Basis-Ressourcendateien enthalten deutschsprachige Texte (`LocalizedStrings.resx`), die englische Fassung liegt als `LocalizedStrings.en.resx` vor. Umfang: WPF-Client 404 KB (de) / 349 KB (en), `Centron.Controls` 129 KB / 125 KB, `Centron.BL` 26 KB / 24 KB. Das Blazor-Portal nutzt `SharedResource.resx` / `SharedResource.en-US.resx` sowie `WebCartResource.resx` / `.en-us.resx`. Fehlermeldungen im Backend sind deutschsprachig (z. B. „Der Beleg hat kein gültiges Datum.", „Die maximale Anzahl an Lizenzen wurde erreicht.").
Aussage: Das System soll alle anwendersichtbaren Texte in deutscher Sprache als Standardsprache bereitstellen und zusätzlich eine englische Sprachfassung über getrennte Ressourcendateien unterstützen.
Ergebnis: Jeder anwendersichtbare Text ist in Deutsch verfügbar; für Texte mit englischer Übersetzung wird bei englischer Spracheinstellung die englische Fassung angezeigt.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Resources/LocalizedStrings.resx (404 KB, deutsch) und LocalizedStrings.en.resx (349 KB) - Begründung: Belegt Standardsprache Deutsch und die zweisprachige Auslegung samt Umfangsdifferenz.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3565, 3577 (deutschsprachige Fehlermeldungen direkt im Code) - Begründung: Zeigt, dass Deutsch auch in nicht lokalisierten Codepfaden die Ausgabesprache ist.
- [SEKUNDÄR] ResXManager.config.xml - Begründung: Werkzeugkonfiguration für die Ressourcenpflege.
- [KONTEXT] docs/getting-started/general-structure.md:114-141 („German-First Language Policy") - Begründung: Formuliert die Sprachvorgabe als Projektregel.
Prüfidee: Für jeden Schlüssel in `LocalizedStrings.en.resx` existiert ein Schlüssel in `LocalizedStrings.resx`; Stichprobe von 20 Oberflächentexten ist deutschsprachig.
Tracelinks: SyRS-048; SwRS-022, SwRS-036
Konsolidierung: nein
Status: belegt; Workaround (Die Umfangsdifferenz von rund 55 KB zwischen deutscher und englischer WPF-Ressourcendatei sowie deutschsprachige Literale direkt im Backend-Code deuten auf eine unvollständige Lokalisierung hin – im Zielsystem zu vereinheitlichen.)
```
```
ID: StRS-019
Titel: Betrieb wahlweise als Windows-Installation oder containerisiert
Ebene: StRS
Typ: nicht-funktional
Akteur: IT-Betrieb des Anwenderunternehmens
Vorbedingung: Eine SQL-Server-Datenbank ist erreichbar.
Fakt: Es existieren WiX-Installationsprojekte (`deployment/centron/CentronSetupProject`, `WebServiceSetupProject`, `WixSharpInstaller`) für Windows. Parallel existieren Dockerfiles für `c-entron-api`, `c-entron-webservice`, `c-entron-demo`, `c-entron-mailcatcher` sowie eine `compose.yaml`, die die Dienste `db` (MSSQL), `webservice` (`/app/Centron.Host.Console`, Port 1234→4321), `smtp` und `nexus` (Port 8050) in einem Bridge-Netzwerk startet. `Centron.BL` zielt auf `net10.0;net10.0-windows`, `Centron.Host` und `Centron.DAO` auf `net10.0` (plattformneutral); nur `Centron.WPF.UI` ist auf `net10.0-windows` mit `UseWPF` festgelegt.
Aussage: Das System soll den Web-Service und das Webportal sowohl als Windows-Dienst als auch als plattformneutrale Container-Anwendung betreibbar machen; die WPF-Clientanwendung bleibt Windows-gebunden.
Ergebnis: Der Web-Service ist über `Centron.Host.Console` unter Linux/Container lauffähig und über HTTP bzw. HTTPS erreichbar; der Windows-Betrieb erfolgt über `Centron.Host.WindowsService`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>`) und src/webservice/Centron.Host/Centron.Host.csproj (`net10.0`) - Begründung: Die Multi-Targeting-Konfiguration ist die technische Voraussetzung für plattformneutralen Serverbetrieb.
- [PRIMÄR] docker/compose/compose.yaml (Dienste db/webservice/smtp/nexus, Volumes für `WebServiceConfig.xml` und `appsettings.Production.json`, `restart: on-failure`) - Begründung: Vollständige, ausführbare Betriebsbeschreibung.
- [PRIMÄR] deployment/centron/WebServiceSetupProject/Product.wxs, deployment/WixSharpInstaller/Program.cs - Begründung: Belegt den alternativen Windows-Installationsweg.
- [KONTEXT] docs/guides/services/web-service-on-linux.md:8-92 (Installation, HTTPS über pfx, systemd-Unit) - Begründung: Beschreibt den Linux-Betrieb einschließlich bekannter Einschränkungen.
Prüfidee: `docker compose up` startet Datenbank, Web-Service und Portal; der Web-Service antwortet auf Port 4321, das Portal auf Port 8050.
Tracelinks: SyRS-039, SyRS-040, SyRS-041, SyRS-043; SwRS-023, SwRS-033, SwRS-034, SwRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Anbindung externer Artikel- und Preisquellen
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer / Vertriebsinnendienst
Vorbedingung: Zugangsdaten für die jeweilige externe Quelle sind konfiguriert.
Fakt: Unter `src/apis/` existieren eigenständige Zugriffsbibliotheken für ITscope (`Centron.APIs.ITscopeDataAccess`), Icecat (`Centron.APIs.IcecatDataAccess`), COP (`Centron.APIs.CopDataAccess`), EGIS (`Centron.APIs.EgisDataAccess`), FinAPI, GLS und Shipcloud. Im Belegkontext existieren die Artikelsuch-Provider `ITscopeExternalArticleSearchProvider`, `EgisExternalArticleSearchProvider`, `CopApiBaseExternalArticleSearchProvider`. Zusätzlich existiert die interne Preisquelle „Aktionspreise" (`ActionPriceBL`, Tabelle `HerstellerArtikAktionspreis`).
Aussage: Das System soll Artikelstammdaten, Verfügbarkeiten und Einkaufspreise aus mehreren externen Quellen parallel abrufen und dem Anwender in einer vergleichenden Preisübersicht („Preisspiegel") gemeinsam mit internen Aktionspreisen darstellen.
Ergebnis: Der Preisspiegel eines Artikels enthält je verfügbarer Quelle mindestens Lieferant, Einkaufspreis, Datum und – soweit vorhanden – Verfügbarkeit.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ArticleSearch/ITscopeExternalArticleSearchProvider.cs, EgisExternalArticleSearchProvider.cs, CopApiBaseExternalArticleSearchProvider.cs - Begründung: Implementieren den parallelen Abruf externer Artikel-/Preisdaten im Belegkontext.
- [PRIMÄR] src/apis/ (7 eigenständige Integrationsprojekte) - Begründung: Belegt die abgegrenzten externen Schnittstellen.
- [SEKUNDÄR] docs/reference/receipts/actionprice-system.md:185-193 (Aufzählung der sieben parallelen Preisquellen) - Begründung: Beschreibt die fachliche Zusammenführung im Preisspiegel.
- [KONTEXT] docs/reference/receipts/actionprice-system.md:299-312 (Validierungs- und Anzeigeregeln der Aktionspreise) - Begründung: Ergänzt die Gültigkeitsregel „Datum innerhalb Gültigkeitszeitraum".
Prüfidee: Für einen Artikel mit Herstellernummer, für den in zwei externen Quellen Preise existieren, enthält der Preisspiegel mindestens zwei Zeilen mit unterschiedlichem Quellenkennzeichen.
Tracelinks: SyRS-034; SwRS-024
Konsolidierung: Kandidat: Sieben Preisquellen mit je eigener Abruf-, Parsing- und Anzeigelogik; im Zielsystem als ein Provider-Interface mit einheitlichem Ergebnismodell zusammenführbar.
Status: belegt
```
```
ID: StRS-021
Titel: Nutzungsbasierte Abrechnung von Managed Services (RMM/MSP)
Ebene: StRS
Typ: funktional
Akteur: Managed-Service-Provider (Anwenderunternehmen)
Vorbedingung: Der Vertrag ist für RMM-Abrechnung konfiguriert und die RMM-Schnittstelle ist erreichbar.
Fakt: `AutomaticFacturaWebServiceBL.CheckRMMArticle` sucht in den Rechnungspositionen den Platzhalter `@@RMMArtikel@@` (in `RichText` oder `Text`), ruft Nutzungsdaten für den Abrechnungszeitraum ab und fügt daraus Positionen ein. Ist der RMM-Dienst nicht erreichbar und werden RMM-Artikel erwartet, wird `RMMServiceUnavailableException` geworfen und die Rechnungserstellung abgebrochen. Der Platzhalter ist in `VariablesCollection.cs:73` als offizielle Variable registriert. Zusätzlich existieren die Module `MspCollectorAppModuleController`, `MSPComparerAppModuleController`, `MspDashboardAppModuleController` mit eigenem Rechteblock `UserRightsConst.MspCollector`.
Aussage: Das System soll aus einem externen Monitoring-/RMM-System periodische Nutzungsmengen beziehen und daraus Rechnungspositionen erzeugen; ist der Bezug nicht möglich, soll keine unvollständige Rechnung entstehen.
Ergebnis: Bei erreichbarem RMM-Dienst enthält die Vertragsrechnung eine Position je genutztem Leistungsmerkmal; bei nicht erreichbarem Dienst wird die Rechnungserstellung mit Fehlermeldung abgebrochen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:721-726, 800, 2412-2414 (`CheckRMMArticle`, `throw new RMMServiceUnavailableException`) - Begründung: Setzt die Regel „keine Rechnung ohne vollständige Nutzungsdaten" technisch durch.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/Variables/VariablesCollection.cs:73 (`"@@RMMArtikel@@"`) - Begründung: Der Platzhalter ist ein definiertes Konfigurationsmerkmal, kein Zufallstext.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2621-2628 (`MspCollector`) - Begründung: MSP-Auswertung ist eigenständig berechtigt.
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md:46-52 („This prevents invoices from being created with incomplete usage data, ensuring customers are billed correctly.") - Begründung: Formuliert die fachliche Absicht der Abbruchregel.
Prüfidee: Bei simulierter Nichterreichbarkeit des RMM-Dienstes und mindestens einer konfigurierten RMM-Artikelreferenz entsteht keine Rechnung; im Protokoll steht die RMM-Fehlermeldung.
Tracelinks: SyRS-029, SyRS-034; SwRS-009, SwRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Mehrstufige Authentifizierung und Anbindung an Unternehmens-Identitätsdienste
Ebene: StRS
Typ: Sicherheit
Akteur: IT-Sicherheitsverantwortlicher des Anwenderunternehmens
Vorbedingung: Die Authentifizierungsverfahren sind in `WebServiceConfig.xml` bzw. den Anwendungseinstellungen konfiguriert.
Fakt: `AuthenticatorFactory` wählt anhand von `SystemAuthenticationMethod` (`None`, `Basic`, `ActiveDirectory`, `OpenIdConnect`) den Authentifikator. OpenID Connect setzt die Lizenz `LicenseGuids.OpenIDConnectAuthentication` und die aktivierte JWT-Einstellung voraus. Zusätzlich prüft `TwoFactorAuthBL.ValidateTwoFactor` bei aktivem `TwoFactorAuthEnabled` einen zweiten Faktor über `RadiusServer` oder `EmailLink`; die Gültigkeitsdauer wird je Benutzer (`TwoFactorValidDurationInDays`) oder global gesetzt, wobei `0` bedeutet: bei jeder Anmeldung.
Aussage: Das System soll die Benutzeranmeldung wahlweise gegen den internen Benutzerstamm, gegen Active Directory oder gegen einen OpenID-Connect-Anbieter durchführen und optional einen zweiten Authentifizierungsfaktor per RADIUS oder E-Mail-Bestätigung erzwingen.
Ergebnis: Bei aktivierter Zwei-Faktor-Authentifizierung und abgelaufener Gültigkeit muss der Benutzer den zweiten Faktor erneut bestätigen, bevor ein Sitzungsticket ausgestellt wird.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:88-146 (Auswahl des Authentifikators, Lizenz- und Aktivierungsprüfung für OpenID Connect) - Begründung: Zentrale, durchgesetzte Verfahrenswahl.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs:33-135 (`ValidateTwoFactor`, `HasToValidateTwoFactor`, tagesbasierte Gültigkeit) - Begründung: Vollständige Regel für die Notwendigkeit des zweiten Faktors.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs:183-193 (`TwoFactorAuthType.RadiusServer` / `.EmailLink`) - Begründung: Abschließende Aufzählung der zweiten Faktoren.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 (Abbruch der Anmeldung bei fehlgeschlagener 2FA) - Begründung: Beweist die Durchsetzung im Anmeldepfad.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml (`TwoFactorAuthEnabled`, `TwoFactorAuthType`, `RadiusServer*`, `MailTwoFactorAuthTimeoutInSeconds`, `TwoFactorValidDurationInDays`) - Begründung: Zeigt die Konfigurationsparameter der Auslieferung.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md - Begründung: Beschreibt die Microsoft-/Entra-ID-Anbindung fachlich.
Prüfidee: Bei `TwoFactorValidDurationInDays = 0` und aktivem 2FA wird bei jeder Anmeldung ein zweiter Faktor angefordert; bei Wert 1 nur einmal je Kalendertag je Kombination aus Benutzer, Anwendung, Maschine und IP-Adresse.
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SyRS-004; SwRS-025, SwRS-026
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: Dokumentenverwaltung und rechtsgeschäftliche Signatur (C-Sign)
Ebene: StRS
Typ: funktional
Akteur: Vertrieb / Kunde
Vorbedingung: Ein Dokument (z. B. Web-Angebot) ist über einen Token für den Empfänger freigegeben.
Fakt: Es existieren die Objektarten `DocumentSigning = 7600133` und `DocumentSigningCustomerReceipts = 7600146`. Im Portal existieren `DocumentSigningPage.razor` und `IsolatedSignaturePad.razor`. Die Legacy-REST-Schnittstelle stellt `GetSharedDocumentByToken`, `SharedDocumentAccepted` und `SignSharedDocument` bereit – jeweils **ohne** `[Authenticate]`-Attribut, also tokenbasiert und ohne Sitzungsanmeldung. Zusätzlich existieren Dokumentenrechte `UserRightsConst.Sales.Documents` (`READ_DOCUMENTS`, `ADD_DOCUMENTS`, `CHANGE_DOCUMENTS`, `DELETE_DOCUMENTS`, Verzeichnisrechte) und der Objekttyp `WebOffer = 7600126`.
Aussage: Das System soll Dokumente an einer Objekt-/Verzeichnisstruktur verwalten und ausgewählte Dokumente über einen zeitlich und inhaltlich begrenzten Token einem externen Empfänger zur Ansicht, Annahme und handschriftlichen Signatur bereitstellen.
Ergebnis: Ein Empfänger kann ein per Token freigegebenes Dokument ohne Benutzerkonto öffnen, annehmen und signieren; die Annahme/Signatur wird am Objekt festgehalten.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetSharedDocumentByToken`, `SharedDocumentAccepted`, `SignSharedDocument`, jeweils ohne `[Authenticate]`) - Begründung: Belegt den bewusst anonymen, tokengesicherten Zugang.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:231, 255 (`DocumentSigning`, `DocumentSigningCustomerReceipts`) - Begründung: Signaturvorgänge sind eigenständige, referenzierbare Objektarten.
- [PRIMÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor - Begründung: Implementiert die Signaturerfassung im Portal.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1884-1901 (`Sales.Documents`) - Begründung: Dokumenten- und Verzeichnisoperationen sind einzeln rechtegeschützt.
- [KONTEXT] Commits `89ccfd650d` „Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)", `cf27c00580` „Ticket 160807 - Fix c-sign document preview and signing document" - Begründung: Belegen C-Sign als aktiv weiterentwickelte Fachfunktion und benennen die Ticketreferenzen.
Prüfidee: Ein gültiger Dokumententoken erlaubt Aufruf und Signatur ohne Anmeldung; nach Signatur ist der Vorgang am zugehörigen Beleg dokumentiert und der Token nicht erneut zur Signatur verwendbar.
Tracelinks: SyRS-010, SyRS-011; SwRS-027
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Anpassbarkeit des Systemverhaltens ohne Programmierung
Ebene: StRS
Typ: nicht-funktional
Akteur: Systemadministrator (Anwenderseite)
Vorbedingung: Der Benutzer besitzt das Recht `UserRightsConst.Administration.SETTINGS`.
Fakt: Es existieren zwei Einstellungsspeicher: die Legacy-Tabelle `Stammdat` mit 728 Konstanten in `AppSettingsConst` und die aktuelle Tabelle `ApplicationSettings` mit 492 Einträgen in `ApplicationSettingID` (nächste freie ID laut Kopfkommentar: 10471). Beide werden über `AppSettingsBL.GetSettings(...)` typisiert gelesen (`GetBool`, `GetInt`, `GetString`, `GetLargeString`, `GetEnum<T>`, `GetDecimal`). `ApplicationSettingDefinitions.cs` (85 KB) hält je Einstellung eine Beschreibung.
Aussage: Das System soll sein fachliches Verhalten (Pflichtfelder, Vorbelegungen, Textbausteine, Formate, Schnittstellenschalter, Automatisierungen) über zentral verwaltete, typisierte Anwendungseinstellungen konfigurierbar machen.
Ergebnis: Eine Verhaltensänderung wie „ZUGFeRD-Rechnung aktiv" oder „Ticket-Kurzbeschreibungspräfix" ist ohne Codeänderung über die Einstellungen erreichbar und wirkt nach dem Speichern.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs (492 Einträge, Kopfkommentar mit ID-Verwaltung) - Begründung: Zentrale, im Code durchgesetzte Registratur der Einstellungen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Settings/AppSettingsConst.cs (728 Einträge) - Begründung: Belegt den parallelen Legacy-Speicher.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:351-374 (`AddShortDescriptionPrefix` liest `IsHelpdeskShortDescriptionPrefixActivated` und `HelpdeskShortDescriptionPrefix` und ersetzt Variablen) - Begründung: Konkretes Beispiel einstellungsgesteuerten Fachverhaltens.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 - Begründung: Zweites Beispiel: Schnittstellenaktivierung per Einstellung.
- [KONTEXT] docs/guides/development/settings-management.md:7-47 - Begründung: Beschreibt die Zweiteilung der Einstellungsspeicher und die ID-Verwaltung.
Prüfidee: Das Umschalten von `IsZugferdInvoiceActive` verändert ohne Neustart des Clients das Ergebnis von `IsZugferdEnabled()` und damit die Rechnungsausgabe.
Tracelinks: SyRS-049; SwRS-028, SwRS-034
Konsolidierung: Kandidat: Zwei parallele Einstellungsspeicher (`Stammdat` / `ApplicationSettings`) bilden dieselbe fachliche Funktion ab; im Zielsystem zwingend zusammenzuführen.
Status: belegt; Workaround (Die Doppelung `Stammdat`/`ApplicationSettings` ist laut Projektdokumentation historisch bedingt; neue Einstellungen dürfen nur noch in `ApplicationSettings` angelegt werden.)
```
```
ID: StRS-025
Titel: Automatisierter, unbeaufsichtigter Hintergrundbetrieb
Ebene: StRS
Typ: funktional
Akteur: IT-Betrieb / Anwenderunternehmen
Vorbedingung: Der Web-Service läuft und die Ausführung von Diensten ist aktiviert (`ExecuteServices`).
Fakt: Der Web-Service-Host registriert 35 Hintergrunddienste (`src/webservice/Centron.Host/AspNetCore/HostedServices/`), darunter `EdiDownloadService`, `EscalationsService`, `ContractEndeService`, `ContractCloseService`, `ReminderService`, `MassUpdateService`, `DataQualityService`, `ExchangeSyncService`, `TelemetryUploadService`, `ArticleImportService`, `AutomaticPriceUpdateService`, `GfkExportService`, `PlmImportService`, `SendMyDayNotificationsService`, `TaskManagmentService`. Alle erben von `ManagedBackgroundService`, das je Dienst über `BackgroundServiceBL.IsServiceEnabled(serviceName)` aktivierbar ist und Start-/Laufzeiten protokolliert. Die Konfiguration `ExecuteServices` in `WebServiceConfig.xml` steuert die Ausführung insgesamt.
Aussage: Das System soll wiederkehrende fachliche Aufgaben (EDI-Abruf, Vertragsende- und -abschlussprüfung, Eskalationen, Erinnerungen, Massenänderungen, Datenqualitätsprüfungen, Kalendersynchronisation, Importe) ohne Benutzerinteraktion zeitgesteuert ausführen und je Aufgabe einzeln aktivierbar machen.
Ergebnis: Für jeden aktivierten Dienst sind Startzeit und letzte Laufzeit im System hinterlegt; deaktivierte Dienste werden übersprungen und protokolliert.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94 (`UpdateStartTime`, `GetIsEnabledCached`, `UpdateLastRunTime`) - Begründung: Einheitliches, durchgesetztes Ausführungs- und Steuerungsmodell aller Hintergrunddienste.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (35 Dienstklassen) - Begründung: Belegt Umfang und Art der automatisierten Aufgaben.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml (`<ExecuteServices>false</ExecuteServices>`) - Begründung: Globaler Schalter der Dienstausführung in der Auslieferungskonfiguration.
- [KONTEXT] docs/Background Service/DataQualityService.md:4-21 - Begründung: Beschreibt Zweck und Taktung eines Beispieldienstes fachlich.
Prüfidee: Wird ein Dienst über `BackgroundServiceBL` deaktiviert, protokolliert der Host innerhalb von 60 Sekunden „… is disabled, skipping execution." und führt keine fachliche Aktion aus.
Tracelinks: SyRS-035, SyRS-045; SwRS-029, SwRS-033, SwRS-037
Konsolidierung: nein
Status: belegt
```
---
## 3. Abgrenzung
Nicht Gegenstand dieser StRS sind:
- Anforderungen an die Delphi-Vorgängeranwendung „c-entron Delphi". Sie wird im Code nur noch als Lizenz-/Versionssonderfall behandelt (`LicenseManager.TryFixCentronDelphiVersionNumber`) und ist nicht Teil des Arbeitsverzeichnisses.
- Als `[Obsolete]` gekennzeichnete Funktionsbereiche (u. a. `UserRightsConst.Monitoring`, `.SupRemo`, `.DirectNow`, `.Riversuite`, `.N13`, `Sales.Cashbox`). Sie sind im Code vorhanden, aber ausdrücklich abgekündigt und werden im Zielsystem nicht benötigt. Siehe `Analysebericht.md`, Abschnitt „Bekannte Lücken".
@@ -0,0 +1,860 @@
# SwRS – Software Requirements Specification
**System:** NEXOWARE c-entron ERP
**Verfahren:** Reverse Requirements Engineering (statische Artefaktanalyse), ISO/IEC/IEEE 29148:2018
**Analysebasis:** Git-Arbeitskopie `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48` (Stand 2026-08-25)
**Erstellt:** 2026-08-25 · **Iteration:** V1 Baseline (Prompt-only), Lauf 01
---
## 0. Zweck dieser Ebene
Die SwRS beschreibt die softwareinternen Strukturen: Komponentenschnitt, Datenmodellkonventionen, softwareinterne Regeln und Persistenzmechanismen. Sie ist die Ebene, auf der die Neuimplementierung entscheiden muss, **welche Struktur übernommen und welche abgelöst wird**. Anforderungen, die eine erkennbar historische Lösung beschreiben, tragen im Feld `Status` den Zusatz `Workaround`.
---
## 1. Architektur und Komponentenschnitt
```
ID: SwRS-001
Titel: Sechsschichtige Anwendungsarchitektur
Ebene: SwRS
Typ: funktional
Akteur: Gesamtsystem
Vorbedingung: Eine Fachfunktion wird vom Client aufgerufen.
Fakt: Die Codebasis ist in sechs Schichten mit je eigenem Objekttyp gegliedert: UI (`Centron.WPF.UI`, `CentronNexus`) → ViewModel (DTO/ViewModel) → `ILogic`/`BL*Logic`/`WS*Logic` (DTO) → `ICentronRestService`/`CentronRestService` (DTO) → `*WebServiceBL` (Entity↔DTO-Wandlung, AutoMapper-Profile unter `Centron.BL/WebServices/ObjectMapperConfiguration/`) → `*BL` (Entity, NHibernate) → Datenbank. `Centron.BL/WebServices` enthält 464 Dateien, `Centron.BL` insgesamt über 2 100.
Aussage: Das System soll den Datenfluss zwischen Oberfläche und Datenbank über klar getrennte Schichten führen, in denen Datenübertragungsobjekte (DTO) und Persistenzentitäten (Entity) nicht vermischt werden; die Umwandlung soll ausschließlich in der `*WebServiceBL`-Schicht erfolgen.
Ergebnis: Persistenzentitäten verlassen den Server nicht; die Oberfläche arbeitet ausschließlich mit DTOs bzw. ViewModels.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/ (464 Dateien, `*WebServiceBL`-Klassen als eigene Schicht) - Begründung: Die physische Trennung der Wandlungsschicht belegt die Architekturregel.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs (239 KB) gegenüber src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (609 KB) - Begründung: Konkretes Paar aus Wandlungs- und Fachlogikschicht derselben Domäne.
- [KONTEXT] docs/getting-started/general-structure.md:5-13 (Schichtentabelle) - Begründung: Beschreibt die Schichten und den je Schicht verwendeten Objekttyp.
- [KONTEXT] docs/reference/architecture/dtos-and-entities.md - Begründung: Erläutert die Trennung von DTO und Entity.
Prüfidee: Kein `CentronRestService`-Rückgabetyp verweist auf einen Typ aus dem Namensraum `Centron.Data.Entities`.
Tracelinks: SyRS-032, SyRS-033; StRS-001
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-002
Titel: Datenmodell der Zugriffsberechtigungen
Ebene: SwRS
Typ: Daten
Akteur: Datenbank / Komponente `AppRightsBL`
Vorbedingung: –
Fakt: Das Rechtemodell besteht aus vier Tabellen mit deutschen Legacy-Namen: `Sichrech` (Rechte, Entität `AppRight` mit `I3D`, `Text`, `Parent`), `Sichgrup` (Gruppen, Entität `AppGroup` mit `I3D`, `Name`, `BranchI3D`, `Status`), `Sichtrus` (Gruppe↔Recht, Entität `AppGroupRightAssignment` mit `GroupI3D`, `RightI3D`) und `Sichmemb` (Benutzer↔Gruppe, Entität `AppUserMember` mit `AppUserI3D`, `GroupI3D`); Benutzer liegen in `Sichbenu` (Entität `AppUser`). Rechte sind hierarchisch (`AppRight.Parent`); beim Zuweisen eines Rechts wird rekursiv auch das übergeordnete Recht zugewiesen (`SaveAndAssignGroupToRight` ruft sich für `selectedRight.Parent` selbst auf). Beim Löschen einer Gruppe werden verwaiste Zuordnungen bereinigt (`DELETE FROM Sichtrus WHERE Gruppe NOT IN (SELECT I3D FROM Sichgrup)`).
Aussage: Das System soll Rechte als hierarchische Struktur führen, Gruppen filialbezogen zuordnen können und bei der Zuweisung eines Rechts automatisch dessen übergeordnete Rechte mitzuweisen, damit Menüzweige erreichbar bleiben.
Ergebnis: Nach Zuweisung eines Unterrechts besitzt die Gruppe auch alle darüberliegenden Rechte; nach Löschung einer Gruppe existieren keine verwaisten Zuordnungen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:261-278 (`SaveAndAssignGroupToRight` mit rekursivem `Parent`-Aufruf) - Begründung: Belegt die Hierarchie als aktive Regel, nicht nur als Datenstruktur.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:578-590 (`ResetDefaultRightGroups` mit Bereinigungs-SQL) - Begründung: Belegt Tabellennamen und Referenzbereinigung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48 (`AppGroup.BranchI3D`) - Begründung: Belegt die Filialzuordnung von Gruppen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:565-573 (SQL-Kommentar zur Erzeugung der Standardrechtestruktur aus `Sichgrup`/`Sichtrus`) - Begründung: Nennt die Tabellen und Spalten explizit.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Rights/DefaultRightsStructure.txt (eingebettete Ressource) - Begründung: Auslieferungsstand der Standardrechtegruppen.
Prüfidee: Nach Zuweisung eines Blattrechts an eine leere Gruppe enthält `Sichtrus` auch die Einträge aller übergeordneten Rechte des Pfads.
Tracelinks: SyRS-009, SyRS-014; StRS-002
Konsolidierung: nein
Status: belegt; Workaround (Deutsche Legacy-Tabellennamen `Sichrech`/`Sichgrup`/`Sichtrus`/`Sichmemb`/`Sichbenu` weichen von der geltenden Namenskonvention ab und sind aus Kompatibilitätsgründen unverändert.)
```
```
ID: SwRS-003
Titel: Wiederherstellbare Standardrechtestruktur
Ebene: SwRS
Typ: funktional
Akteur: Komponente `AppRightsBL`
Vorbedingung: Ein Benutzer löst das Zurücksetzen der Standardrechtegruppen aus.
Fakt: `AppRightsBL.ResetDefaultRightGroups` liest die eingebettete Ressource `Centron.BusinessLogic.Administration.Rights.DefaultRightsStructure.txt` (Format: Gruppenname, Tabulator, kommaseparierte Recht-IDs), löscht in einer Transaktion alle Gruppen mit diesen Namen, bereinigt verwaiste Zuordnungen in `Sichtrus` und `Sichmemb` und legt die Gruppen mit ihren Rechten neu an. Die Gruppen „Administratoren" und „RMM Systemuser Group" sind laut Kommentar von der Erzeugung der Ressourcendatei ausgenommen.
Aussage: Das System soll eine ausgelieferte Standardrechtestruktur bereitstellen und wiederherstellbar machen, ohne dabei die Administratorgruppe oder Systemgruppen zu verändern.
Ergebnis: Nach dem Zurücksetzen existieren alle in der Ressourcendatei genannten Gruppen mit exakt den dort hinterlegten Rechten; benutzerdefinierte Gruppen und die Administratorgruppe bleiben unverändert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:563-640 (`ResetDefaultRightGroups`, `GetDefaultRightsStructure`, `GetDefaultRightsStructureFileContent`) - Begründung: Vollständiger Mechanismus einschließlich Transaktionsklammer und Ressourcenzugriff.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:565-573 (SQL-Kommentar mit Ausschluss von „Administratoren" und „RMM Systemuser Group") - Begründung: Belegt den Ausschluss der Systemgruppen.
Prüfidee: Nach dem Zurücksetzen entspricht die Rechtezuordnung jeder Standardgruppe zeichengenau der Ressourcendatei; eine zuvor angelegte eigene Gruppe existiert unverändert weiter.
Tracelinks: SyRS-012, SyRS-013, SyRS-014; StRS-002
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-004
Titel: Objektartschlüssel als systemweiter Verweismechanismus
Ebene: SwRS
Typ: Daten
Akteur: Gesamtsystem
Vorbedingung: Ein Datensatz verweist auf ein Objekt unbekannten Typs.
Fakt: `CentronObjectKindNumeric` definiert 205 Objektarten mit stabilen numerischen Werten. Der Kopfkommentar schreibt vor: „Neue Arten MÜSSEN am Ende eingefügt werden, ansonsten kriegen die Leute bei dem Web-Service ein Problem"; neue .NET-Konstanten beginnen ab 7600000, die nächste freie ist 7600154 laut Fußkommentar. Polymorphe Verweise werden systemweit als Paar `ObjectI3D` + `ObjectKind` geführt; in Legacy-Tabellen entspricht dem das Paar `AnlageI3D` + `AnlageArt`. Der Änderungsprotokoll-Datensatz `ChangeLog` verwendet dasselbe Paar.
Aussage: Das System soll Verweise auf Objekte unterschiedlicher Art einheitlich über das Paar aus numerischer Objektart und Objekt-ID abbilden; die numerischen Werte sollen unveränderlich sein.
Ergebnis: Ein Protokoll-, Dokument- oder Verweisdatensatz kann ohne typspezifische Tabelle auf jedes Geschäftsobjekt zeigen; bestehende Werte bleiben über Versionsgrenzen hinweg stabil.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:6-12 (Warnkommentar zur Stabilität der Werte), :263 (nächste freie Konstante) - Begründung: Explizite, im Code festgehaltene Kompatibilitätsregel.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:127-137 (`ObjectI3D`, `ObjectKind`) - Begründung: Konkrete Anwendung des Verweismusters.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:266-317 (`IsReceipt`, `IsCustomerReceipt`, `IsSupplierReceipt`, `GetAssetName`) - Begründung: Belegt die fachliche Gruppierung der Objektarten im Code.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:129-143 (`AnlageI3D` + `AnlageArt`, Wertetabelle 1..6, 22) - Begründung: Ordnet die Legacy-Entsprechung zu und bestätigt die Wertegleichheit.
Prüfidee: Für jede Objektart, auf die ein `ChangeLog`-Eintrag verweisen kann, existiert genau ein Wert in `CentronObjectKindNumeric`; kein bestehender Wert wurde zwischen zwei Releases geändert.
Tracelinks: SyRS-016; StRS-003, StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-005
Titel: Lizenzkomponente als Singleton mit einmaliger Initialisierung
Ebene: SwRS
Typ: funktional
Akteur: Komponente `LicenseManager`
Vorbedingung: Die Anwendung startet.
Fakt: `LicenseManager` ist ein Singleton mit `Initialize(LicensingManagerSettings)`; ein zweiter Aufruf wirft „The LicenseManager was already initialized. It can't be initialized multiple times."; ein Zugriff auf `Instance` vor der Initialisierung wirft „The LicenseManager is not initialized. Make sure to call the Initialize method at application startup.". Es existieren drei Konfigurationsvarianten: `SettingsForWebService()` (echter `OfficeClient`, Dateicache, Zusatzdaten Datenbank-ID/-Name/-Erstelldatum/-Eigentümer-SID, Maschinenname, Windows-Dienstname), `SettingsForCentronNet(Func<Task<string>>)` (`FakeOfficeClient`, `CheckIfLicenseIsValidForHardwareIDs = false`) und `SettingsForTests(Dictionary<Guid,string>)` (im Ablauf erzeugtes 1024-Bit-Schlüsselpaar, feste Hardware-ID `Dongle.12345678`). Im DEBUG-Build des Clients wird eine Sonderkonfiguration ohne `FakeOfficeClient` verwendet.
Aussage: Das System soll die Lizenzverwaltung als genau einmal initialisierte, prozessweite Komponente führen, deren Bezugsquelle je Ausführungsumgebung (Server, Client, Test) austauschbar ist.
Ergebnis: Client und Server verwenden dieselbe Lizenzlogik bei unterschiedlicher Bezugsquelle; Tests laufen ohne Lizenzserver.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:174-195 (Singleton-Erzwingung mit beiden Fehlermeldungen) - Begründung: Belegt die Einmaligkeitsregel unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:47-115 (`SettingsForWebService` inkl. Zusatzdaten für die Lizenzserver-Identifikation) - Begründung: Belegt, welche Systemmerkmale zur Lizenzbindung übertragen werden.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:140-173 (`SettingsForTests`) - Begründung: Belegt die Testbarkeit ohne externen Dienst.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/FakeOfficeClient.cs - Begründung: Implementiert den Client-Bezugsweg über den Web-Service.
Prüfidee: Ein zweiter `Initialize`-Aufruf im selben Prozess führt zur genannten Ausnahme; ein Test mit `SettingsForTests` läuft ohne Netzwerkzugriff.
Tracelinks: SyRS-007, SyRS-008, SyRS-015; StRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-006
Titel: Vererbungsstruktur der Belegentitäten
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: –
Fakt: `ReceiptBase : BaseEntity, IReceiptBase` definiert die für alle Belegarten gemeinsamen Merkmale: Belegkopf (`Number`, `Date`, `Version`, `State`, `EditorI3D`, `DirectoryI3D`), Filiale (`BranchI3D`, `BranchOrigin`), Währung (`CurrencyI3D`, `CurrencyFactor`, `CurrencyString`, `ExclusiveOfVAT`), Kontakt (`Receiver`, `Phone`, `Fax`, `Email`), Anschrift (`AddressI3D`, `ContactPersonI3D`, `Street`, `HasPostOfficeBox`, `PostOfficeBox`, `Zip`, `City`, `ContactName`, `CountryI3D`), Prüfspur (`CreatedByI3D`, `CreatedAt`, `CreatedThroughApplicationVersion`, `ChangedByI3D`, `ChangedAt`, `ChangedThroughApplicationVersion`, `ChangedThroughApplication`), Systemfelder (`ConcurrencyControlGuid`, `CustomUpdateArticlePricesAndTexts`) sowie vier Empfängerrollen (`ReceiptReceiver`, `ReceiptReceiverInvoice`, `ReceiptReceiverDelivery`, `ReceiptReceiverLicense`). Abstrakt bleiben `ReceiptKind` und die vier Positionsoperationen `GetReceiptItems`, `SetReceiptItems`, `AddItem`, `RemoveItem`. Ergänzende Merkmale werden über Kennzeichnungsschnittstellen zugeschaltet: `IReceiptWithIsCash`, `IReceiptWithPaymentCondition`, `IReceiptWithEsr`, `IReceiptWithContingent`, `IReceiptClosedThroughRMA`, `IReceiptWithCustomStringProperty1`, `IReceiptItemWithOrigin`, `IReceiptItemWithBarcodes`, `IReceiptItemWithOnlyPriceValue`, `ICustomerReceiptBase`, `ISupplierReceiptBase`.
Aussage: Das System soll gemeinsame Belegmerkmale in einer abstrakten Basisklasse führen und belegartspezifische Merkmale über Kennzeichnungsschnittstellen zuschalten, sodass die gemeinsame Verarbeitungslogik typunabhängig arbeiten kann.
Ergebnis: Neue Belegarten erfordern keine Änderung der gemeinsamen Verarbeitungslogik, sondern nur die Implementierung der Basisklasse und der zutreffenden Kennzeichnungsschnittstellen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72 - Begründung: Vollständige Basisdefinition mit allen gemeinsamen Feldern und abstrakten Mitgliedern.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3764, 3816, 3823, 3549 (Typprüfungen `receipt is IReceiptWithIsCash`, `IReceiptClosedThroughRMA`, `IReceiptWithEsr`, `IReceiptContract`) - Begründung: Belegt, dass die Verarbeitungslogik über Kennzeichnungsschnittstellen verzweigt.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:13-55 - Begründung: Ordnet den Belegarten Entitätsklassen und Ablageorte zu.
Prüfidee: Alle sieben Kundenbeleg- und fünf Lieferantenbelegentitäten erben von `ReceiptBase` und implementieren `ReceiptKind` mit dem passenden Wert aus `CentronObjectKindNumeric`.
Tracelinks: SyRS-016, SyRS-017, SyRS-019, SyRS-020, SyRS-022, SyRS-023, SyRS-024; StRS-005
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-007
Titel: Zweigleisige Belegpersistenz über Legacy-Tabellen und moderne Sichten
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: Ein Beleg wird geladen oder gespeichert.
Fakt: Für jede Belegart existieren nebeneinander (a) die deutschsprachige Legacy-Tabelle (`AngKopf`/`AngPos`, `AufKopf`/`AufPos`, `LiefKopf`/`LiefPos`, `RechKopf`/`RechPos`, `VertragKopf`/`VertragPos`, `GutKopf`/`GutPos`, `AbholKopf`/`AbholPos`), (b) eine englischsprachige Sicht (`Offers`/`OfferItems`, `Orders`/`OrderItems`, …) und (c) Versionstabellen (`*KopfVersions`/`*PosVersions`) mit zugehörigen Sichten. Das **Lesen** erfolgt über die modernen Entitäten und Sichten. Das **Schreiben** erfolgt über eigene `SaveReceipt*Repository`-Klassen, die die modernen Entitäten in temporäre Legacy-Entitäten (`Centron.Entities/Entities/DbEntities/`, 39 Dateien; Mappings unter `Centron.DAO/Mappings/TemporaryEntities/`) übertragen: Kopffelder in `SynchronizeReceiptData`, Positionsfelder in `SynchronizeReceiptItemData`. Ein neues Feld muss laut Projektdokumentation an zehn Stellen nachgezogen werden.
Aussage: Das System soll den Lese- und den Schreibpfad der Belegpersistenz konsistent halten; ein persistiertes Belegfeld muss auf beiden Pfaden vollständig abgebildet sein.
Ergebnis: Ein neu eingeführtes Belegfeld ist nach Speichern und erneutem Laden unverändert vorhanden; die Versionstabelle enthält dieselbe Spalte.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/DbEntities/ (39 temporäre Legacy-Entitäten) und src/backend/Centron.DAO/Mappings/TemporaryEntities/ - Begründung: Belegt die Existenz des zweiten, legacy-orientierten Schreibpfads im Code.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:174-190 (Zehn-Punkte-Checkliste, „Critical Save Warning") - Begründung: Beschreibt die Konsistenzpflicht und die konkrete Fehlerwirkung („the value may load correctly from the view but will not be persisted on save").
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:249-255 (Beschreibung der `SaveReceipt*Repository`-Klassen) - Begründung: Nennt die Methodennamen des Schreibpfads.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:104-181 (Spaltenliste `VertragKopf`/`VertragPos`, Versionierungs-SQL) - Begründung: Konkretisiert die Legacy-Struktur für die Belegart Vertrag.
Prüfidee: Ein Ende-zu-Ende-Test, der ein neues Belegfeld setzt, speichert, neu lädt und zusätzlich den Rohwert in der Legacy-Tabelle prüft, schlägt fehl, wenn nur die moderne Zuordnung ergänzt wurde.
Tracelinks: SyRS-017, SyRS-018; StRS-005, StRS-014
Konsolidierung: Kandidat: Legacy-Tabelle, moderne Sicht, temporäre Legacy-Entität und Repository bilden dieselbe fachliche Struktur viermal ab; im Zielsystem zwingend auf ein Modell zu reduzieren.
Status: belegt; Workaround (Der doppelte Persistenzpfad ist ein historisch bedingter Kompatibilitätsmechanismus zur Delphi-Vorgängeranwendung und die aufwendigste Einzelstruktur der Belegverarbeitung.)
```
```
ID: SwRS-008
Titel: Versionstabellen als strukturgleiche Kopien
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: Eine neue Belegversion wird gespeichert.
Fakt: Zu jeder Belegtabelle existiert eine Versionstabelle mit identischer Spaltenmenge, ergänzt um `OriginalI3D` (Verweis auf den Ursprungsdatensatz) und – bei Positions-Versionstabellen – `KopfVersionsI3D` (Verweis auf die Kopfversion); die Spalten `I3D` und `OriginalI3D` der Quelltabelle werden nicht übernommen. Das Kopieren erfolgt mit einem dynamisch erzeugten Feldliste-INSERT (`DoGetFieldList()`, Muster `INSERT INTO AngKopfVersions (…) SELECT …, I3D AS OriginalI3D FROM AngKopf WHERE I3D = @receiptId`).
Aussage: Das System soll Belegversionen als vollständige Momentaufnahmen in strukturgleichen Versionstabellen ablegen; jede Spalte der Quelltabelle muss in der Versionstabelle mit identischem Datentyp vorhanden sein.
Ergebnis: Eine Belegversion ist vollständig rekonstruierbar; ein fehlendes Feld in der Versionstabelle führt zu einem Laufzeitfehler beim Versionieren, nicht zu stillem Datenverlust.
Belege:
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 („Version tables … are exact 1:1 copies", INSERT-Muster, „⚠️ Critical Warning") - Begründung: Beschreibt Struktur, Erzeugungsmechanismus und Fehlerwirkung vollständig.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:150-181 - Begründung: Wiederholt die Regel für Verträge mit konkretem SQL.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3629 (`SaveReceiptVersion(receipt, previousReceiptVersion)`) - Begründung: Belegt den Aufrufpunkt im Speicherpfad.
Prüfidee: Ein Vergleich der Spaltenmengen von `AngKopf` und `AngKopfVersions` ergibt Gleichheit bis auf `I3D`/`OriginalI3D`; dasselbe gilt für alle sieben Belegarten.
Tracelinks: SyRS-017; StRS-014
Konsolidierung: nein
Status: belegt; Workaround (Die Konsistenz wird nicht durch ein Datenbank-Constraint, sondern durch Entwicklerdisziplin und einen Laufzeitfehler gesichert. Der `PRIMÄR`-Beleg für die Kopiermechanik selbst – `AssetHeadDAO.SaveAssetVersion` – wurde in dieser Iteration nicht im Detail gelesen; die Struktur stützt sich auf Projektdokumentation und den Aufrufpunkt im Speicherpfad.)
```
```
ID: SwRS-009
Titel: Delegation belegartspezifischer Logik über ein Strategiemuster
Ebene: SwRS
Typ: funktional
Akteur: Komponente `ReceiptBL`
Vorbedingung: Eine belegartabhängige Entscheidung ist zu treffen.
Fakt: `ReceiptBL` verwendet durchgängig `this._specificLogics.Execute(receipt, f => f.<Operation>(…))` bzw. `Execute<TResult, TReceipt>(…)`, um an eine belegartspezifische Implementierung von `IReceiptSpecificLogic` zu delegieren. Es existieren mindestens 13 Implementierungen: `OfferSpecificLogic`, `OrderSpecificLogic`, `DeliveryListSpecificLogic`, `InvoiceSpecificLogic`, `PickupListSpecificLogic`, `CreditVoucherSpecificLogic`, `ContractSpecificLogic` sowie die Lieferantenvarianten `SupplierOrderSpecificLogic`, `SupplierInvoiceSpecificLogic`, `SupplierDeliveryListSpecificLogic`, `SupplierCreditVoucherSpecificLogic`. Delegierte Entscheidungen sind u. a.: `GetNumberGroup`, `HasRightToCreateANewReceipt`, `HasRightToCreateANewReceiptOnlyOwnBranch`, `HasRightToEditReceipt`, `HasRightToEditReceiptOnlyOwnBranch`, `HasRightToViewReceipt`, `BlockNewReceiptsDunningLevel`, `TakesPlaceInLimitCalculation`, `GetUsedLimitAmount`, `UpdatesStock`, `IncrementsStock`, `UpdatesIntake`, `CreatesAccountActivities`, `WarnIfUserMakesNegativeArticleBooking`, `UserNeedsRightToMakeNegativeArticleBooking`, `TryLockReceipt`, `UnLockReceipt`, `SaveReceipt`, `SaveReceiptVersion`, `BeforeReceiptIsSaved`, `AfterReceiptIsSaved`, `OnReceiptNewVersion`, `GetParentDirectoryForReceipts`, `GetNewVersionUpdateDateSetting`, `GetNewVersionUpdateEditorSetting`, `FillReportGroupParameters`.
Aussage: Das System soll alle belegartabhängigen Entscheidungen über eine gemeinsame Schnittstelle mit je einer Implementierung pro Belegart auflösen, sodass die gemeinsame Belegverarbeitung frei von Fallunterscheidungen nach Belegart bleibt.
Ergebnis: Das Hinzufügen einer neuen Belegart erfordert eine neue `IReceiptSpecificLogic`-Implementierung, aber keine Änderung an `ReceiptBL`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs (25 KB) - Begründung: Definiert den vollständigen Vertrag der belegartspezifischen Entscheidungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/{Offers,Orders,DeliveryLists,Invoices,PickupLists,CreditVouchers,ContractLists,Supplier*}/…SpecificLogic.cs (13 Implementierungen, 23–46 KB) - Begründung: Belegt die vollständige Umsetzung je Belegart.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3841, 3846, 3854-3857, 10201, 10277, 10284, 10304 (Delegationsaufrufe) - Begründung: Belegt die durchgängige Verwendung des Musters an sicherheits- und persistenzrelevanten Stellen.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:230-235 („SpecificLogics Pattern") - Begründung: Benennt das Muster.
Prüfidee: Eine Textsuche nach `switch (receipt.ReceiptKind)` in `ReceiptBL.cs` liefert keine fachlichen Fallunterscheidungen; alle Verzweigungen laufen über `_specificLogics`.
Tracelinks: SyRS-017, SyRS-018, SyRS-021, SyRS-023, SyRS-025, SyRS-029; StRS-005, StRS-006, StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-010
Titel: Reflexionsbasierte Auflösung generischer Belegoperationen
Ebene: SwRS
Typ: funktional
Akteur: Komponente `ReceiptBL`
Vorbedingung: Eine Belegoperation wird ohne statisch bekannten Belegtyp aufgerufen.
Fakt: `ReceiptBL.SaveReceipt(IReceiptBase receipt, …)` und `ReceiptBL.CreateNewVersion(CentronObjectKindNumeric receiptKind, …)` ermitteln zur Laufzeit die generische Überladung über Reflexion (`this.GetType().GetMethods().First(f => f.Name == nameof(...) && f.IsGenericMethod).MakeGenericMethod(...)`) und rufen sie per `Invoke` auf. Die Typparameter werden aus `receipt.GetType()` und `receipt.ReceiptKind.GetReceiptItemType()` bzw. `receiptKind.GetReceiptType()` abgeleitet.
Aussage: [HYPOTHESE] Das System soll generische Belegoperationen ohne Reflexion auflösen, da Reflexion Typfehler erst zur Laufzeit sichtbar macht und die Ausführungsgeschwindigkeit beeinträchtigt.
Ergebnis: Belegoperationen sind zur Übersetzungszeit typgeprüft.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3517-3521 (`SaveReceipt`, Reflexionsauflösung) - Begründung: Belegt das Muster im zentralen Speicherpfad.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3063-3067 (`CreateNewVersion`, dasselbe Muster) - Begründung: Belegt die Wiederholung des Musters.
Prüfidee: Ein Aufruf von `SaveReceipt` mit einem Belegtyp ohne passende Positionsklasse führt zu einer Laufzeitausnahme statt zu einem Übersetzungsfehler.
Tracelinks: SyRS-017; StRS-005
Konsolidierung: nein
Status: HYPOTHESE
Fehlende Information: Ob die Reflexionsauflösung bewusst gewählt wurde (z. B. wegen der nicht-generischen Legacy-Schnittstellensignatur) oder eine ablösbare Altlast ist, geht aus den Artefakten nicht hervor. Es fehlt ein Kommentar oder eine Entwurfsnotiz; ohne diese Information ist die Zielarchitekturentscheidung nicht belegbar. Zur Klärung durch Fachexperten vorgemerkt.
```
---
## 2. Fachkomponenten
```
ID: SwRS-011
Titel: Komponentenschnitt der Ticketverarbeitung
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Helpdesk
Vorbedingung: –
Fakt: Der Ordner `src/backend/Centron.BL/Sales/Support/` enthält 53 Klassen mit klarer Aufgabenteilung: `HelpdeskBL` (Kernlogik, Speichern, Rechteprüfung), `HelpdeskSettingsBL` (87 KB, Zustände und Konfiguration), `EscalationBL` (69 KB, Eskalationen), `HelpdeskHistoryBL` (Verlauf), `HelpdeskCustomerBL`, `HelpdeskReplacementBL` (Variablenersetzung), `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL`, `HelpdeskTimerArticleBookingBL`, `HelpdeskTimerLogBL`, `HelpdeskSearchBL`, `HelpdeskOverviewFilterBL`, `HelpdeskCloseBL`, `HelpdeskForwardBL`, `HelpdeskPatternBL`, `HelpdeskMailBL`, `HelpdeskSendMailBL`, `UpdateHelpdeskBL`, `HelpdeskConnectionNumberBL`, `AdressstammReplacementBL`.
Aussage: Das System soll die Ticketverarbeitung in fachlich abgegrenzte Komponenten für Kernlogik, Konfiguration, Zeiten, Eskalation, Suche, Weiterleitung, Vorlagen, Abschluss und Benachrichtigung gliedern.
Ergebnis: Eine Änderung an der Eskalationslogik berührt weder die Zeiterfassung noch die Suchlogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/ (53 Klassen mit den genannten Namen und Größen) - Begründung: Der Komponentenschnitt ist unmittelbar aus der Dateistruktur ablesbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`new HelpdeskSettingsBL(this.Session).GetClosedHelpdeskState()`) - Begründung: Belegt die Auslagerung der Zustandskonfiguration in eine eigene Komponente.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EscalationsService.cs, ValidateHelpdeskFingerprintService.cs - Begründung: Belegt die zeitgesteuerten Anteile der Ticketverarbeitung.
Prüfidee: Die Ticketzustände sind ausschließlich über `HelpdeskSettingsBL` erreichbar; `HelpdeskBL` enthält keine hartcodierten Zustands-IDs.
Tracelinks: SyRS-026, SyRS-027; StRS-007
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-012
Titel: Konfigurierbare Ticketzustände statt fester Zustandsaufzählung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `HelpdeskSettingsBL`
Vorbedingung: –
Fakt: Im Gegensatz zum Belegzustand (`ReceiptState`, drei feste Werte) existiert für Tickets **keine** Zustandsaufzählung im Code. Der Abschlusszustand wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` aus der Konfiguration ermittelt und mit `entity.HelpdeskState` verglichen. Ticketarten, Haupt- und Unterkategorien sind ebenfalls Stammdaten (`HelpdeskType`, `MainCategory`, `SubCategory1`, `SubCategory2`) mit eigenen Anlagerechten (`ADD_NEW_HELPDESK_TYPE`, `ADD_NEW_HELPDESK_MAIN_CATEGORY`, `ADD_NEW_HELPDESK_SUB_CATEGORY1`, `ADD_NEW_HELPDESK_SUB_CATEGORY2`). Für Web-Anfragen existiert separat die feste Aufzählung `RequestStateEnum` mit `Requested = 0` („Angefragt"), `Veryfied = 1` („Verifiziert"), `Accepted = 2` („Angenommen"), `Denied = 3` („Abgelehnt").
Aussage: Das System soll Ticketzustände, -arten und -kategorien als anwenderpflegbare Stammdaten führen und den Abschlusszustand über eine Konfiguration bestimmen; Zustandsprüfungen im Code sollen ausschließlich gegen diese Konfiguration erfolgen.
Ergebnis: Ein Anwender kann eigene Ticketzustände anlegen; der Abschlussmechanismus arbeitet ohne Codeänderung mit dem konfigurierten Abschlusszustand.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`GetClosedHelpdeskState()`) - Begründung: Belegt die Konfigurationsabhängigkeit des Abschlusszustands unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:367-374 (Variablenersetzung mit `@@Hauptkategorie@@`, `@@Unterkategorie1@@`, `@@Unterkategorie2@@`, `@@Typ@@`, `@@Ansprechpartner@@`) - Begründung: Belegt Kategorien und Typ als Stammdatenobjekte mit Namensattribut.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Customers/Enum/RequestStateEnum.cs - Begründung: Belegt die abweichende, feste Zustandsaufzählung für Web-Anfragen.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1963-1967 (Anlagerechte für Typ und Kategorien) - Begründung: Belegt die Pflegbarkeit als berechtigte Anwenderhandlung.
Prüfidee: Nach Anlage eines neuen Ticketzustands und dessen Festlegung als Abschlusszustand greift die Rechteprüfung `CLOSE_REQUEST` auf den neuen Zustand.
Tracelinks: SyRS-026; StRS-007, StRS-024
Konsolidierung: Kandidat: Zwei Zustandsmodelle nebeneinander (konfigurierbare Ticketzustände, feste `RequestStateEnum` für Web-Anfragen); im Zielsystem zu vereinheitlichen.
Status: belegt
```
```
ID: SwRS-013
Titel: Komponentenschnitt der Belegpreis- und Positionsverarbeitung
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Belege
Vorbedingung: –
Fakt: Die Positions- und Preisverarbeitung ist auf spezialisierte Komponenten unter `src/backend/Centron.BL/Sales/Receipts/Internal/` verteilt: `ReceiptItemPriceBL` (Preisberechnung, `ChangeBasePrice`), `ReceiptPriceHelperBL` (`CalculateReceiptPrices` mit `NetPrice`/`GrossPrice`, `CalculateReceiptItemPrices`), `ReceiptItemTimerBL` (Ticketzeiten, 104 KB), `ReceiptBarcodeBL` (Barcodes, 98 KB), `ReceiptArticleBookingBL` (Lagerbuchung, 50 KB), `ReceiptContractHelperBL` (Kontingente, 62 KB), `ReceiptProvisionBL` (Provision, 45 KB), `ReceiptAddressAndContactPersonHelperBL` (55 KB), `ReceiptItemSalutationAndAgreementReplacementBL` (26 KB), `ReceiptReceiverUpdaterBL`, `ReceiptItemAccountBL`, `ReceiptEsrBL` (Schweizer Einzahlungsschein), `ReceiptLayoutItemKindPdfHelperBL`. Ergänzend auf gleicher Ebene: `ReceiptItemBL` (225 KB), `ReceiptLogBL` (74 KB), `ReceiptProgressionBL`, `ReceiptCartBL`, `ReceiptCartReleaseSystemBL`, `DownPaymentBL` (Anzahlungen), `ReceiptTemplateBL`.
Aussage: Das System soll Preisberechnung, Positionsverwaltung, Barcodeverwaltung, Lagerbuchung, Kontingentverrechnung, Provisionsermittlung und Anschriftenpflege in eigenständigen Komponenten kapseln, die von der Belegkernlogik aufgerufen werden.
Ergebnis: Eine Änderung der Preisberechnung erfordert keine Änderung der Belegkernlogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ (14 Komponenten mit den genannten Namen und Größen) - Begründung: Komponentenschnitt unmittelbar aus der Dateistruktur ablesbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:8699-8702 (`_receiptPriceHelperBL.CalculateReceiptPrices(receipt).NetPrice / .GrossPrice`) - Begründung: Belegt die Delegation der Preisberechnung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:9075 (`_receiptItemPriceBL.ChangeBasePrice(item, minPrice)`) - Begründung: Belegt die Delegation der Preisänderung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7250-7252 (`FillReceiptWithProvision`, `FillReceiptWithBarcodes`, `FillReceiptWithTimerI3Ds`) - Begründung: Belegt die Delegation beim Laden ergänzender Belegdaten.
Prüfidee: `ReceiptBL.cs` enthält keine eigene Preisformel; alle Preisberechnungen laufen über `ReceiptPriceHelperBL` bzw. `ReceiptItemPriceBL`.
Tracelinks: SyRS-017, SyRS-021, SyRS-025; StRS-005, StRS-008, StRS-015, StRS-016
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-014
Titel: Verteilung der Vertragsabrechnung auf drei Komponenten
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Vertragsabrechnung
Vorbedingung: –
Fakt: Die Vertragsabrechnung ist auf drei Ebenen verteilt: `AutomaticFacturaBL.Contracts` (124 KB, Ermittlung fälliger Verträge und Abrechnungsparameter), `AutomaticFacturaWebServiceBL` (126 KB, Rechnungserzeugung `CreateInvoiceToContractComplete`, Zählerdaten, Staffelpreise, RMM-Positionen) und `ReceiptContractBL` (46 KB, Kontingentverrechnung, Geräte-/Zählerverwaltung, Stammblattzuordnung) sowie `ContractSpecificLogic` (46 KB). Die Rechnungserzeugung selbst delegiert an `ReceiptWebServiceBL.ForwardReceipt(...)`. Die Ablaufmessung erfolgt über `PerformanceTracer.StartTrace()` mit `PostTrace`-Marken.
Aussage: Das System soll die Vertragsabrechnung in Fälligkeitsermittlung, Rechnungserzeugung und vertragsspezifische Nachverarbeitung gliedern und die Rechnungserzeugung über den regulären Belegweiterverarbeitungspfad ausführen.
Ergebnis: Eine aus einem Vertrag erzeugte Rechnung durchläuft dieselben Validierungen wie eine manuell erfasste Rechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1815-1841 (`receiptBL.ForwardReceipt(...)` mit `originReceipts`) - Begründung: Belegt die Nutzung des regulären Weiterverarbeitungspfads.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs (124 KB) - Begründung: Belegt die eigenständige Fälligkeitsermittlung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ContractLists/ReceiptContractBL.cs (46 KB) - Begründung: Belegt die vertragsspezifische Nachverarbeitung.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1702-1704 (`PerformanceTracer.StartTrace()`) - Begründung: Belegt eine eingebaute Laufzeitmessung dieses Vorgangs.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:275-283 - Begründung: Beschreibt die Aufgabenteilung.
Prüfidee: Eine per Vertragsabrechnung erzeugte Rechnung erhält eine Nummer aus dem Rechnungsnummernkreis und durchläuft die Kreditlimitprüfung.
Tracelinks: SyRS-018, SyRS-029; StRS-006, StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-015
Titel: Kapselung der elektronischen Rechnungserzeugung
Ebene: SwRS
Typ: Schnittstelle
Akteur: Komponente `InvoiceZugferdBL`
Vorbedingung: –
Fakt: `InvoiceZugferdBL` ist eine partielle Klasse (120 KB) mit den öffentlichen Einstiegspunkten `GetZugferFormat`, `GetZugferdFileName`, `GenerateZugferdFile`, `CreateZugferdConformPdfDocument` und dem internen Bereich „ZUGFeRD file generator". Die PDF-Erzeugung nutzt `DevExpress`-Klassen (`PdfDocumentProcessor`, `PdfZugferdVersion`, `PdfZugferdConformanceLevel`, `AttachZugferdInvoice`). Die Formatermittlung wird über `Session.Advanced.Cache.GetOrAdd($"GetZugferdFormatInternal{exportZUGFeRD}", …)` zwischengespeichert. Für österreichische E-Rechnung existiert separat `Centron.Api.EbInterface`, für den Import `ZugferdImportController` und `Centron.Gateway/ZUGFeRD21_Extended`.
Aussage: Das System soll die Erzeugung und den Import elektronischer Rechnungen in eigenen Komponenten kapseln, die Formatentscheidung zwischenspeichern und länderspezifische Formate über getrennte Bibliotheken bedienen.
Ergebnis: Eine neue Normversion erfordert eine Erweiterung von `ZugferdKind` und der Zuordnungstabellen, nicht aber Änderungen an der Belegverarbeitung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:52, 85-238 - Begründung: Belegt Kapselung, Einstiegspunkte und Zwischenspeicherung.
- [PRIMÄR] src/apis/Centron.Api.EbInterface/ - Begründung: Belegt die getrennte Bibliothek für das österreichische Format.
- [PRIMÄR] src/webservice/Centron.Controllers/Controllers/v1/Receipts/ZugferdImportController.cs, src/backend/Centron.Gateway/ZUGFeRD21_Extended/ - Begründung: Belegt den getrennten Importpfad.
- [KONTEXT] docs/guides/development/xrechnung.md:6-9 („Would be nice to switch to this in the future instead of creating our own implementation.") - Begründung: Dokumentiert die Eigenimplementierung und die erwogene Ablösung durch eine Fremdbibliothek.
Prüfidee: Ein Import einer ZUGFeRD-Rechnung über `ZugferdImportController` erzeugt einen Lieferantenbeleg; die Erzeugung einer Ausgangsrechnung nutzt ausschließlich `InvoiceZugferdBL`.
Tracelinks: SyRS-030; StRS-012
Konsolidierung: nein
Status: belegt; Workaround (Die ZUGFeRD-Erzeugung ist eine Eigenimplementierung; die Projektdokumentation benennt den Wechsel auf eine etablierte Open-Source-Bibliothek als wünschenswert.)
```
```
ID: SwRS-016
Titel: Anonymisierungskomponente mit Löschprotokoll
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `DataSecurityBL`
Vorbedingung: –
Fakt: `DataSecurityBL` (85 KB) implementiert für mindestens drei Datenmodelle getrennte Anonymisierungsroutinen: Kunden-Ansprechpartner (deutsche Legacy-Felder `Fon`, `Fax`, `KdEmail`, `Kommentar`, `Strasse`, `Plz`, `Ort`), Accounts-Ansprechpartner (englische Felder `Name`, `Matchcode`, `Phone`, `Fax`, `Email`, `Comment`, `Department`, `GeoInfoLatitude`, `GeoInfoLongitude`) und weitere. Die zugehörigen SQL-Anweisungen sind im Quelltext als auskommentierte Referenz enthalten (Zeilen 863–1098). Jeder überschriebene Wert wird über `DoAppendDeleteProtocol(deleteProtocol, Feldbezeichnung, Altwert)` mit deutscher Feldbezeichnung („E-Mail 1", „Mailing an E-Mail 1", „Freies Feld 1", „Abteilung", „Bild", „Active Directory SID", „Webseite", „Kommentar") protokolliert. Zusätzlich existiert die Funktion „Datenbank bereinigen" mit eigenem Recht `ACCESS_CLEANUP_DATABASE` und dem Feature-Schalter `ModuleFeatures.IsDsgvoDatabaseCleanupAvailable`.
Aussage: Das System soll für jede personenbezogene Datenstruktur eine Anonymisierungsroutine bereitstellen, die vor jeder Überschreibung den bisherigen Wert unter einer anwenderverständlichen Feldbezeichnung protokolliert.
Ergebnis: Das Löschprotokoll ist als Nachweis gegenüber der betroffenen Person und der Aufsichtsbehörde verwendbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1195-1275 (Protokollierung je Feld mit deutscher Bezeichnung) - Begründung: Belegt das Protokollmuster unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1598-1630 (zweite Anonymisierungsroutine für das Accounts-Modell) - Begründung: Belegt die Mehrfachimplementierung.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:36, 66 (`ACCESS_CLEANUP_DATABASE` und `ModuleFeatures.IsDsgvoDatabaseCleanupAvailable`) - Begründung: Belegt die doppelte Absicherung der Datenbankbereinigung.
Prüfidee: Das Löschprotokoll eines anonymisierten Ansprechpartners enthält für jedes zuvor belegte Feld genau eine Zeile mit Feldbezeichnung und Altwert.
Tracelinks: SyRS-028; StRS-013
Konsolidierung: Kandidat: Drei parallele Anonymisierungsroutinen für strukturell gleichartige Kontaktdaten; im Zielsystem als deklarative, feldattributgesteuerte Anonymisierung zusammenführbar.
Status: belegt
```
```
ID: SwRS-017
Titel: Attributgesteuerte Änderungsprotokollierung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `ChangeTrackingEventListener`
Vorbedingung: Eine Entität wird über NHibernate aktualisiert.
Fakt: Die Protokollierung ist ein `IPreUpdateEventListener`. Sie greift nur für Typen mit `[ChangeTrackingConfiguration(ObjectKind = …)]` und protokolliert nur Eigenschaften mit `[TrackChanges]`. Je geändertem Feld entsteht ein `ChangeLog` mit `ObjectI3D`, `ObjectKind`, `DisplayName` (`entity.ToString()`), `OldValue`, `NewValue`, `Property`, `Date`, `AppUser`; alle Textfelder werden auf 4000 Zeichen gekürzt (`Shorten(4000)`). Die Beschreibung folgt dem festen Muster „{Property} wurde von {OldValue} auf {NewValue} geändert.". Typ- und Attributauswertung werden in `ConcurrentDictionary` zwischengespeichert. Die Protokollierung unterbleibt mit Warnung, wenn (a) der Schlüssel kein `int` ist oder (b) `LoggedInUserManager.AppUserI3D` nicht gesetzt ist. Ausnahmen werden protokolliert, brechen die Aktualisierung aber nicht ab (`return false`, kein Veto).
Aussage: Das System soll Feldänderungen an gekennzeichneten Entitäten automatisch und unabhängig vom aufrufenden Anwendungsfall protokollieren; ein Fehler in der Protokollierung darf die fachliche Aktualisierung nicht verhindern.
Ergebnis: Jede Aktualisierung eines mit `[TrackChanges]` versehenen Feldes erzeugt einen Protokolleintrag mit Alt- und Neuwert, Zeitpunkt und Benutzer; fehlt der Benutzerkontext, wird der Vorgang mit Warnung übersprungen.
Belege:
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-99 (Ereignisbehandlung, Zwischenspeicherung, Ausnahmebehandlung ohne Veto) - Begründung: Vollständige Steuerlogik.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:112-142 (`CreateChangeLog`, Kürzung, Beschreibungsmuster, Voraussetzungen) - Begründung: Belegt Feldinhalte und Abbruchbedingungen.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:179-207 (`GetEntityData` mit Attributauswertung) - Begründung: Belegt die Attributsteuerung.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/LogHourlySurchargeRateChangesListener.cs - Begründung: Belegt einen zweiten, fachspezifischen Protokollierungs-Listener.
Prüfidee: Die Änderung eines `[TrackChanges]`-Feldes ohne gesetzten `LoggedInUserManager.AppUserI3D` erzeugt eine Warnung im Anwendungsprotokoll, aber keinen `ChangeLog`-Eintrag; die Änderung selbst wird gespeichert.
Tracelinks: SyRS-046; StRS-014
Konsolidierung: nein
Status: belegt; Workaround (Der Benutzerkontext wird über eine statische Klasse `LoggedInUserManager` übergeben; ist sie nicht gesetzt – etwa in Hintergrunddiensten –, entfällt die Protokollierung stillschweigend. Dies ist eine Lücke in der Revisionssicherheit.)
```
```
ID: SwRS-018
Titel: Datenmodell- und Namenskonventionen der Datenbank
Ebene: SwRS
Typ: Daten
Akteur: Datenbank
Vorbedingung: Eine Tabelle wird neu angelegt.
Fakt: Verbindliche Konventionen: alle Objekte im Schema `dbo` mit ausdrücklichem Präfix; Primärschlüssel stets `I3D` als `int IDENTITY(1,1) NOT NULL` mit gruppiertem Primärschlüsselindex; Fremdschlüsselspalten enden auf `I3D` mit dem Namen der referenzierten Tabelle als Präfix; Prüfspalten `CreatedByI3D`, `CreatedDate`, `ChangedByI3D`, `ChangedDate`; logisches Löschen über `IsDeleted`, `DeletedByI3D`, `DeletedDate`; Texte als `nvarchar` (nicht `varchar`); Datum/Zeit als `datetime2(2)` bzw. `datetime2(0)`; Wahrheitswerte als `bit`; Tabellennamen in PascalCase, Plural für Entitätssammlungen, Singular für Nachschlagetabellen; nicht gruppierte Indizes nach dem Muster `IX_Tabelle_Spalte1_Spalte2`. Bestehende deutsche Namen bleiben aus Kompatibilitätsgründen unverändert; neue Namen sind englisch. Die Konvention wird über `ScriptHelpers.AddTableIfNotExists` technisch unterstützt, das `I3D` und den Primärschlüssel automatisch erzeugt.
Aussage: Das System soll für alle neuen Datenbankobjekte eine einheitliche Namens-, Schlüssel- und Prüfspaltenkonvention anwenden und das logische Löschen dem physischen vorziehen.
Ergebnis: Jede neue Tabelle besitzt `I3D` als Identitätsprimärschlüssel, Prüfspalten und – sofern Datensätze gelöscht werden können – die Löschkennzeichnung.
Belege:
- [KONTEXT] docs/guides/database/database-conventions.md:5-99 - Begründung: Vollständige Konventionsdefinition mit Beispielen.
- [KONTEXT] docs/reference/database/script-rules.md:49-57 (automatische `I3D`-Erzeugung, Regeln für Prüfspalten, Ausnahme für unveränderliche Historientabellen) - Begründung: Beschreibt die technische Durchsetzung und die begründeten Ausnahmen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/ScriptHelpers.cs - Begründung: Implementiert die Konvention in den Hilfsmethoden, die alle Skripte verwenden.
- [PRIMÄR] src/backend/Centron.Entities/Entities/ (1 179 Entitätsdateien) und src/backend/Centron.DAO/Mappings/ (983 Zuordnungsdateien) - Begründung: Umfang des nach diesen Konventionen abgebildeten Datenmodells.
Prüfidee: Eine Stichprobe von 20 in den letzten 50 Skripten angelegten Tabellen erfüllt alle genannten Konventionen.
Tracelinks: SyRS-039; StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-019
Titel: Rechteabhängige Rücksetzung von Preisänderungen
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `ReceiptBL`
Vorbedingung: Ein Beleg mit geänderten Einkaufs- oder Verkaufspreisen wird gespeichert.
Fakt: Im Speicherpfad wird `UpdateArticlePositionsPurchasePriceAndSellPriceIfUserDoesNotHaveRightToChangeThem(currentUser, receipt, previousReceiptVersion)` aufgerufen. Für jede Belegart existieren getrennte Rechte für Einkaufs- und Verkaufspreisänderung: `Offer.CHANGE_PURCHASE_PRICE = 20400233` / `CHANGE_PRICE = 20400285`, `Order` 20400234 / 20400286, `DeliveryList` 20400242 / 20400287, `PickUpList` – / 20400288, `Invoice` 20400091 / 20400289, `CreditVoucher` – / 20400290, `Contracts` – / 20400291; zusätzlich `Offer.CAN_CHANGE_PROJECT_PURCHASE_PRICE = 20400308`. Ferner wird `UpdateArticlePositionsPurchasePriceEqualsSellPrice`, `UpdateArticlePositionsNotDiscountable` und `UpdateOnlyPriceValue` aufgerufen.
Aussage: Das System soll Preisänderungen eines Benutzers ohne das belegartspezifische Preisänderungsrecht beim Speichern auf die Werte der Vorgängerversion zurücksetzen, statt den Speichervorgang abzulehnen.
Ergebnis: Ein Benutzer ohne Preisänderungsrecht kann den Beleg speichern; die Preise entsprechen danach den Werten vor seiner Änderung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3694 (`UpdateArticlePositionsPurchasePriceAndSellPriceIfUserDoesNotHaveRightToChangeThem`) - Begründung: Der Methodenname und die Parameter (`currentUser`, `previousReceiptVersion`) belegen die Rücksetzungsstrategie unmittelbar.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2204-2205, 2236-2237, 2264-2265, 2296, 2315-2316, 2340, 2383 - Begründung: Belegt die belegartspezifische Trennung von Einkaufs- und Verkaufspreisrecht.
Prüfidee: Ein Benutzer ohne `Order.CHANGE_PRICE` ändert einen Auftragspositionspreis und speichert; nach dem Neuladen steht der ursprüngliche Preis.
Tracelinks: SyRS-017, SyRS-021; StRS-002, StRS-005, StRS-015
Konsolidierung: Kandidat: Sieben belegartspezifische Rechtepaare bilden dieselbe fachliche Regel ab; im Zielsystem als ein Recht mit Belegart-Geltungsbereich zusammenführbar.
Status: belegt
```
```
ID: SwRS-020
Titel: Datenmodell der Provisionsermittlung
Ebene: SwRS
Typ: Daten
Akteur: Fachbereich Provision
Vorbedingung: –
Fakt: Das Provisionsmodell umfasst sieben Entitäten unter `src/backend/Centron.Entities/Entities/Sales/Receipts/`: `ReceiptProvisionSchema` (Schema), `ReceiptProvisionSchemaItem` (Schemazeile), `ReceiptProvisionSchemaCustomerAssignment` (Kundenzuordnung), `ReceiptProvisionItemEntity` (ermittelter Provisionswert je Belegposition), `ReceiptProvisionEmployeeGoal` (Mitarbeiterziel), `ReceiptProvisionEmployeeLevel` (Mitarbeiterstufe). Die Berechnung erfolgt in `ReceiptProvisionBL`, die Schemaverwaltung in `ReceiptProvisionSchemaBL`. Schemas besitzen eine zeitliche Gültigkeit, die vom Hintergrunddienst `UpdateExpiredProvisionSchemasService` stündlich fortgeschrieben wird.
Aussage: Das System soll Provisionsschemas mit Zeilen, Kundenzuordnung und mitarbeiterbezogenen Zielen und Stufen führen und ermittelte Provisionswerte je Belegposition persistieren.
Ergebnis: Zu jeder provisionsrelevanten Belegposition ist der ermittelte Provisionswert und das zugrunde liegende Schema nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvisionSchema.cs, ReceiptProvisionSchemaItem.cs, ReceiptProvisionSchemaCustomerAssignment.cs, ReceiptProvisionItemEntity.cs, ReceiptProvisionEmployeeGoal.cs, ReceiptProvisionEmployeeLevel.cs - Begründung: Vollständiges Entitätenmodell der Domäne.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptProvisionBL.cs, ReceiptProvisionSchemaBL.cs - Begründung: Zugehörige Fachlogikkomponenten.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs - Begründung: Belegt die zeitliche Gültigkeit als aktiv verwaltetes Merkmal.
Prüfidee: Nach Belegerfassung existiert je provisionsrelevanter Position ein `ReceiptProvisionItemEntity`-Datensatz mit Verweis auf das angewandte Schema.
Tracelinks: SyRS-013; StRS-016
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-021
Titel: Getrennte Auswertungskomponenten je Statistikart
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Statistik
Vorbedingung: –
Fakt: Auswertungen sind auf drei Ebenen getrennt: `src/backend/Centron.BL/Statistics/` (16 Klassen, u. a. `ContractStatistics/ContractEvaluationBL.cs` mit 87 KB), `src/backend/Centron.Entities/Entities/Statistics/` (35 Entitäten) und `src/backend/Centron.DAO/Statistics/`. Die Auswertung wird über `ReportDataBL` (92 KB) und die Berichtsmaschine (`src/backend/Centron.BL/ReportEngine/`, 26 Klassen; `Centron.Interfaces/ReportEngine`, `CentronReportEngine`) an ein Berichtsformat übergeben. Es existiert ein Modul „Reportserver" mit Recht `REPORTSERVER = 20800044` sowie das Recht `UPLOAD_PORTAL_REPORTS = 99999458`, dessen Kommentar es als Sonderrecht ausschließlich in c-entron-eigenen Datenbanken ausweist.
Aussage: Das System soll Auswertungsdaten, Auswertungslogik und Berichtsdarstellung in getrennten Komponenten führen und die Berichtsvorlagenverwaltung als eigenständig berechtigte Funktion bereitstellen.
Ergebnis: Eine Änderung an einer Berichtsvorlage erfordert keine Änderung an der Auswertungslogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Statistics/, src/backend/Centron.BL/ReportEngine/, src/backend/Centron.DAO/Statistics/, src/backend/Centron.Entities/Entities/Statistics/ - Begründung: Physische Trennung der drei Ebenen.
- [PRIMÄR] src/backend/Centron.BL/ReportEngine/ReportDataBL.cs (92 KB, `ConvertReportToPdfStream`, `ArchivePdf`) - Begründung: Zentrale Berichtserzeugung.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:21 (`UPLOAD_PORTAL_REPORTS` mit Kommentar „Special Right: Only in c-entron databases …") - Begründung: Belegt ein herstellerinternes Sonderrecht.
Prüfidee: Ein Bericht kann ohne Änderung an `ContractEvaluationBL` neu gestaltet werden.
Tracelinks: SyRS-013; StRS-017
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-022
Titel: Lokalisierung über Ressourcendateien je Assembly
Ebene: SwRS
Typ: Daten
Akteur: Alle Anwendungsteile
Vorbedingung: Ein anwendersichtbarer Text wird ausgegeben.
Fakt: Es existieren sieben Ressourcenpaare: `Centron.BL/Resources/LocalizedStrings.resx|.en.resx` (26/24 KB), `Centron.WPF.UI/Resources/LocalizedStrings.resx|.en.resx` (404/349 KB), `Centron.Controls/Resources/LocalizedStrings.resx|.en.resx` (129/125 KB), `CentronNexus/SharedResource.resx|.en-US.resx` (7/7 KB), `CentronNexus/WebCart/Resource/WebCartResource.resx|.en-us.resx` (19/18 KB), `CentronNexus/WebCart/Resource/CountriesResource.resx|.en-us.resx` (16/16 KB), `CentronNexus.OutlookAddIn/SharedResource.resx` (1 KB, ohne englische Fassung). Der Zugriff erfolgt über die generierte Klasse `LocalizedStrings.Designer.cs` (53 KB in `Centron.BL`). Die Pflege wird durch `ResXManager.config.xml` unterstützt.
Aussage: Das System soll anwendersichtbare Texte je Assembly in eigenen Ressourcendateien führen, sodass Backend-, Client- und Portaltexte unabhängig voneinander gepflegt werden können.
Ergebnis: Ein Text ist über einen typisierten Bezeichner (`LocalizedStrings.<Schlüssel>`) erreichbar; die Sprachfassung wird zur Laufzeit anhand der Spracheinstellung gewählt.
Belege:
- [PRIMÄR] Auflistung aller `*.resx` außerhalb von `bin`/`obj` mit Pfaden und Größen - Begründung: Belegt Aufteilung und Umfang objektiv.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:74, 82, 103, 164-165, 202 (`LocalizedStrings.<Schlüssel>`) - Begründung: Belegt die typisierte Verwendung im Backend.
- [SEKUNDÄR] ResXManager.config.xml - Begründung: Werkzeugunterstützung der Ressourcenpflege.
- [KONTEXT] docs/guides/ui/localization.md - Begründung: Beschreibt die Verwendung in XAML, Code-Behind und Fachlogik.
Prüfidee: Ein Wechsel der Spracheinstellung auf Englisch ändert die Beschriftungen im WPF-Client; für Schlüssel ohne englische Entsprechung bleibt der deutsche Text stehen.
Tracelinks: SyRS-048; StRS-018
Konsolidierung: Kandidat: Sieben getrennte Ressourcenbestände mit teilweise gleichlautenden Texten; im Zielsystem als ein Übersetzungsbestand zusammenführbar.
Status: belegt
```
```
ID: SwRS-023
Titel: Drei austauschbare Hostvarianten für den Web-Service
Ebene: SwRS
Typ: funktional
Akteur: Web-Service
Vorbedingung: –
Fakt: Die Serverfunktionalität liegt in `Centron.Host` (`net10.0`, `CentronHost.cs`) und wird von drei Startprojekten gehostet: `Centron.Host.Console` (Konsolenanwendung, in Docker über `command: /app/Centron.Host.Console` gestartet), `Centron.Host.WindowsService` (Windows-Dienst) und – für die moderne API – `Centron.Controllers`, das in denselben Prozess eingebunden ist. Echtzeitfunktionen laufen über SignalR-Hubs (`AvailabilityStatusHub`, `ChatHub`, `NotificationsHub`, `TapiClientHub`) mit einer schlüsselbasierten Autorisierung (`SecretKeyHandler`, `SecretKeyRequirement`), deren Schlüssel in `WebServiceConfig.xml` als `<SecretKey>` und in der Portalkonfiguration als `Notifications.SecretKey` hinterlegt ist.
Aussage: Das System soll die Serverfunktionalität unabhängig von der Hostvariante bereitstellen und Echtzeitbenachrichtigungen über eine schlüsselgesicherte Verbindung zwischen Portal und Web-Service austauschen.
Ergebnis: Dieselbe Serverfunktionalität ist über Konsolenprozess und Windows-Dienst identisch verfügbar; Echtzeitkanäle sind nur mit korrektem gemeinsamem Schlüssel nutzbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs, Centron.Host.Console/, Centron.Host.WindowsService/ - Begründung: Belegt die Trennung von Funktionalität und Hostvariante.
- [PRIMÄR] src/webservice/Centron.Host/RealTimeServices/ (`AvailabilityStatusHub`, `ChatHub`, `NotificationsHub`, `TapiClientHub`, `SecretKeyHandler`, `SecretKeyRequirement`) - Begründung: Belegt Echtzeitkanäle und deren Autorisierungsmechanismus.
- [PRIMÄR] docker/compose/WebServiceConfig.xml (`<SecretKey>` mit Base64-Wert) und src/nexus/CentronNexus.Host/appsettings.json (`Notifications.SecretKey`) - Begründung: Belegt den gemeinsamen Schlüssel als Konfigurationsgegenstück.
- [PRIMÄR] docker/compose/compose.yaml (`command: /app/Centron.Host.Console`) - Begründung: Belegt die Konsolenvariante als Containerstartpunkt.
Prüfidee: Ein Portal mit falschem `Notifications.SecretKey` erhält keine Echtzeitbenachrichtigungen; die übrige Funktionalität bleibt nutzbar.
Tracelinks: SyRS-035, SyRS-040; StRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-024
Titel: Einheitliche Anbieterstruktur der externen Artikelsuche
Ebene: SwRS
Typ: Schnittstelle
Akteur: Komponente Artikelsuche
Vorbedingung: Eine Artikelsuche mit externer Quelle wird ausgeführt.
Fakt: Unter `src/backend/Centron.BL/Sales/Receipts/ArticleSearch/` liegen `ArticleSearchBL` (56 KB), `SearchTextParser` (18 KB) und drei Anbieterklassen mit gleichlautendem Namensmuster: `ITscopeExternalArticleSearchProvider` (14 KB), `EgisExternalArticleSearchProvider` (18 KB), `CopApiBaseExternalArticleSearchProvider` (10 KB). Die eigentlichen Protokollimplementierungen liegen in eigenen Projekten unter `src/apis/` mit jeweils gleicher Binnenstruktur (`Data/`, `Parser/`, `Properties/`, teils `SoapTemplates/` bzw. `RequestTemplates/`).
Aussage: Das System soll externe Artikelquellen über gleichartig aufgebaute Anbieterkomponenten einbinden, deren Protokoll- und Auswertungslogik von der Suchlogik getrennt ist.
Ergebnis: Eine neue externe Quelle erfordert eine neue Anbieterklasse und ein neues Zugriffsprojekt, aber keine Änderung an `ArticleSearchBL`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ArticleSearch/ (drei Anbieter mit gleichem Namensmuster) - Begründung: Belegt die einheitliche Anbieterstruktur.
- [PRIMÄR] src/apis/Centron.APIs.ITscopeDataAccess/, .EgisDataAccess/, .CopDataAccess/, .IcecatDataAccess/ (je `Data/`, `Parser/`) - Begründung: Belegt die gleichartige Binnenstruktur der Zugriffsprojekte.
- [PRIMÄR] tests/apis/ (vier Testprojekte, je eines pro externem Zugriffsprojekt) - Begründung: Belegt die eigenständige Testbarkeit je Anbieter.
Prüfidee: Alle drei Anbieterklassen implementieren dieselbe Schnittstelle und liefern strukturgleiche Ergebnisobjekte an `ArticleSearchBL`.
Tracelinks: SyRS-034; StRS-020
Konsolidierung: Kandidat: Siehe StRS-020 – im Zielsystem als ein Anbietervertrag mit einheitlichem Ergebnismodell.
Status: belegt
```
---
## 3. Sicherheitsrelevante Softwareinterna
```
ID: SwRS-025
Titel: Vererbungsstruktur der Authentifikatoren
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `Authenticator`
Vorbedingung: –
Fakt: Alle Authentifikatoren erben von der abstrakten Klasse `Authenticator(DAOSession, AuthObject, ILicenseManager) : BaseBL, IAuthenticator`, die den gemeinsamen Ablauf `Authenticate()` → `GetTicket()` → `AuthenticateUser(...)` mit Rechteprüfung, Lizenzprüfung, Ticketerzeugung, IP-Vermerk und Versionsprotokollierung vorgibt. Nur `AuthenticateInternal()` ist abstrakt. Implementierungen: `BasicAuthenticator` (Benutzerstamm), `ActiveDirectoryAuthenticator` (12 KB), `OpenIdConnectAuthenticator`, `WebAccountAuthenticator`, `FallbackAuthenticator` (Kette), `FailingAuthenticator` (immer fehlschlagend mit Meldung). Das Basisobjekt `AuthObject` trägt `RequestId` (GUID je Anmeldeversuch), `RemoteAddress`, `AppVersion`, `ApplicationName`, `MachineName` und überschreibt `ToString()` zur Protokollierung.
Aussage: Das System soll den sicherheitsrelevanten Anmeldeablauf einmalig in einer Basisklasse festlegen, sodass jede Authentifizierungsart dieselben Rechte-, Lizenz- und Protokollierungsschritte durchläuft und nur die Identitätsprüfung austauschbar ist.
Ergebnis: Eine neue Authentifizierungsart erbt automatisch Rechte-, Lizenz- und Ticketlogik; Umgehungen sind nicht möglich, ohne die Basisklasse zu verändern.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:51-155 (abstrakte Basisklasse mit festgelegtem Ablauf, nur `AuthenticateInternal` abstrakt) - Begründung: Belegt den Schablonenmethoden-Ansatz unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:21-43 (`AuthObject` mit `RequestId` und `ToString()`) - Begründung: Belegt die durchgängige Nachvollziehbarkeit jedes Anmeldeversuchs über eine Vorgangskennung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/ (6 Implementierungen) - Begründung: Belegt den Umfang der Austauschbarkeit.
Prüfidee: Für jede Authentifikator-Implementierung wird bei erfolgreicher Anmeldung genau ein Ticket erzeugt und die Lizenzprüfung durchlaufen; die `RequestId` erscheint in allen Protokolleinträgen desselben Anmeldeversuchs.
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SyRS-006; StRS-022
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-026
Titel: Ablage und Prüfung von Benutzerkennwörtern
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponenten `BasicAuthenticator`, `WebAccountBL`
Vorbedingung: Ein Benutzer meldet sich mit Benutzername und Kennwort an.
Fakt: `BasicAuthenticator.AuthenticateInternal` bildet über `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` einen SHA-1-Wert und sucht damit direkt den Benutzerdatensatz: `GetEntity(where => where.Name == Auth.UserName && where.Password == decodedPassword)`. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. `WebAccountBL.LoginWithWebAccount` verwendet dasselbe Verfahren (`SHA1Decoder.GetDecodedSHA1String(password)`, Vergleich `f.Password == cryptedPw`) für Portalkonten. Es findet kein Vergleich in konstanter Zeit statt; das Kennwort ist Teil der Datenbankabfrage.
Aussage: [HYPOTHESE] Das System soll Benutzerkennwörter mit einem benutzerindividuellen Zufallswert (Salt) und einem für Kennwörter geeigneten, rechenintensiven Verfahren ableiten und speichern; der derzeit verwendete ungesalzene SHA-1-Wert erfüllt diese Anforderung nicht.
Ergebnis: Kennwörter sind gegen Rainbow-Table- und Offline-Angriffe geschützt; ein Datenbankabzug erlaubt keine praktikable Rückrechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50 (`SHA1Decoder.GetDecodedSHA1String`, Vergleich in der Abfrage, Kommentar `// TODO the password should be salted!!!`) - Begründung: Belegt Verfahren und die den Entwicklern bekannte Unzulänglichkeit unmittelbar im Code.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:56-61 (dasselbe Verfahren für Web-Accounts) - Begründung: Belegt, dass der Mangel beide Kontoarten betrifft.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:166-170 (`CryptoUtils.CreateSalt(32)`, `CryptoUtils.CreatePasswordHash(deviceId, salt)`) - Begründung: Belegt, dass eine gesalzene Ableitungsfunktion im System vorhanden ist, aber nur für Ticketkennungen und nicht für Kennwörter verwendet wird.
- [KONTEXT] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1263 (`contact.WebKennwort = null`) - Begründung: Belegt, dass Portalkennwörter als personenbezogenes Datum an der Kontaktentität geführt werden.
Prüfidee: Zwei Benutzer mit identischem Kennwort besitzen in der Datenbank denselben Kennwortwert – der Nachweis bestätigt das Fehlen eines Salts. Zielzustand: unterschiedliche Werte bei identischem Kennwort.
Tracelinks: SyRS-003; StRS-002, StRS-011, StRS-022
Konsolidierung: Kandidat: Zwei getrennte Kennwortprüfungen (`BasicAuthenticator` für Mitarbeiter, `WebAccountBL` für Portalkonten) mit identischem Verfahren; im Zielsystem als ein Identitätsdienst zusammenzuführen.
Status: HYPOTHESE
Fehlende Information: Der **Ist-Zustand** (ungesalzenes SHA-1, Vergleich in der Datenbankabfrage) ist durch `PRIMÄR`-Belege eindeutig nachgewiesen. Als `[HYPOTHESE]` gekennzeichnet ist ausschließlich die **Soll-Aussage**: Ob eine Umstellung auf ein gesalzenes, rechenintensives Verfahren im Zielsystem möglich ist, hängt von der Migrationsstrategie für bestehende Kennwörter und von der Kompatibilität mit der Delphi-Vorgängeranwendung ab, die denselben Benutzerstamm nutzt. Diese Randbedingung ist aus den Artefakten nicht ableitbar und durch Fachexperten zu klären.
```
```
ID: SwRS-027
Titel: Portalkomponenten der Dokumentensignatur
Ebene: SwRS
Typ: funktional
Akteur: Webportal
Vorbedingung: –
Fakt: Die Signaturfunktion besteht aus `DocumentSigningPage.razor` (Seitenkomponente mit eigenem `.razor.css`) und `IsolatedSignaturePad.razor` (gekapselte Unterschriftenfläche). Die zugehörigen Serveraufrufe sind `GetSharedDocumentByToken`, `SharedDocumentAccepted` und `SignSharedDocument` in der Legacy-REST-Schnittstelle. Für Ticketsignaturen existiert zusätzlich das Recht `DELETE_HELPDESK_SIGNATURE = 20800143` („Unterschrift aus Zeit löschen"). Objektarten: `DocumentSigning = 7600133`, `DocumentSigningCustomerReceipts = 7600146`.
Aussage: Das System soll die Unterschriftenerfassung als eigenständige, gekapselte Oberflächenkomponente bereitstellen, deren Ergebnis über einen tokengebundenen Serveraufruf am Geschäftsobjekt festgehalten wird; das Entfernen einer erfassten Unterschrift soll ein eigenes Recht erfordern.
Ergebnis: Eine erfasste Unterschrift ist dem Dokument bzw. der Ticketzeit zugeordnet und kann nur mit dem Löschrecht entfernt werden.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor, DocumentSigningPage.razor.css - Begründung: Belegt die gekapselte Oberflächenkomponente.
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetSharedDocumentByToken`, `SharedDocumentAccepted`, `SignSharedDocument`) - Begründung: Belegt den tokengebundenen Serveraufruf.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1974 (`DELETE_HELPDESK_SIGNATURE = 20800143`) - Begründung: Belegt das eigenständige Löschrecht.
- [KONTEXT] CentronRights.md:55-57 („Unterschrift aus Zeit löschen") - Begründung: Fachliche Beschreibung des Rechts.
Prüfidee: Eine im Portal erfasste Unterschrift ist nach dem Speichern am Beleg sichtbar; ein Benutzer ohne `DELETE_HELPDESK_SIGNATURE` kann sie nicht entfernen.
Tracelinks: SyRS-010; StRS-023
Konsolidierung: nein
Status: belegt
```
---
## 4. Konfiguration, Betrieb, Build
```
ID: SwRS-028
Titel: Typisierter Zugriff auf Anwendungseinstellungen über Gruppenklassen
Ebene: SwRS
Typ: Daten
Akteur: Komponente `AppSettingsBL` / `AppSettingsGroupBL`
Vorbedingung: Eine Fachkomponente benötigt Konfigurationswerte.
Fakt: Fachkomponenten greifen nicht direkt auf die Einstellungstabellen zu, sondern über `AppSettingsBL.GetSettings(params ApplicationSettingID[])` bzw. `GetSettings(AppSettingsConst)` und lesen typisiert mit `GetBool(id, default)`, `GetInt`, `GetString`, `GetLargeString`, `GetEnum<T>`, `GetDecimal`. Schreibzugriffe laufen über `GetSettingsForUpdate(...)`, `Update*` und `SaveSettings()`. Zusammengehörige Einstellungen werden in Gruppenklassen gebündelt (`AppSettingsGroupBL`, 153 KB; `AppSettingsGroupWebServiceBL`), die typisierte DTOs wie `ReceiptInvoiceSettingsDTO`, `JwtSettings`, `AuthenticationSettings`, `TextBlockSettings` liefern.
Aussage: Das System soll den Zugriff auf Anwendungseinstellungen ausschließlich über typisierte Gruppenklassen führen, die Standardwerte bei fehlendem Eintrag liefern, sodass Fachkomponenten keine Kenntnis der Speicherstruktur benötigen.
Ergebnis: Eine fehlende Einstellung führt nicht zu einem Fehler, sondern zum hinterlegten Standardwert; die Speicherstruktur ist für die Fachkomponente unsichtbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:34, 38, 46 (`_appSettingsBL.GetJwtSettings()`, `GetAuthenticationSettings()`) - Begründung: Belegt die Gruppenklassen im sicherheitskritischen Pfad.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 (`GetSettings(...).GetBool(..., false)`) - Begründung: Belegt typisierten Zugriff mit Standardwert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:151-152, 233-245 (`GetSettings(AppSettingsConst.TicketReleaseTime).GetInt(...)`, `GetSettingsForUpdate(...)`, `UpdateInt`, `SaveSettings`) - Begründung: Belegt Lese- und Schreibpfad.
- [KONTEXT] docs/guides/development/settings-management.md:63-115, 147-156 - Begründung: Beschreibt Gruppenklassen, Datentypen und Standardwertregel als Projektvorgabe.
Prüfidee: Das Löschen eines Einstellungsdatensatzes führt beim nächsten Lesen zum im Code angegebenen Standardwert und nicht zu einem Fehler.
Tracelinks: SyRS-049; StRS-024
Konsolidierung: Kandidat: `AppSettingsConst` (728 Einträge, Tabelle `Stammdat`) und `ApplicationSettingID` (492 Einträge, Tabelle `ApplicationSettings`) bilden dieselbe fachliche Funktion ab; die Zusammenführung ist im Zielsystem zwingend.
Status: belegt
```
```
ID: SwRS-029
Titel: Gemeinsame Basisklasse aller Hintergrunddienste
Ebene: SwRS
Typ: funktional
Akteur: Web-Service-Host
Vorbedingung: –
Fakt: Alle 35 Hintergrunddienste erben von `ManagedBackgroundService : BackgroundService` und implementieren nur `ServiceName` (Bezeichner für Aktivierung und Protokollierung), `GetExecutionInterval()` (Grundintervall) sowie wahlweise `ExecuteService`/`ExecuteServiceAsync` und `InitializeService`/`InitializeServiceAsync`. Belegte Grundintervalle: 1 Minute (`TelemetryFlushService`, `ObjectFulltextIndexUpdateService`, `DocumentFulltextIndexUpdateService`) und 1 Stunde (`DataQualityService`, `ValidateHelpdeskFingerprintService`, `UpdateExpiredProvisionSchemasService`, `UpdateArticleAndMaterialGroupTaxRatesService`, `RefreshIntakeService`, `PlmImportService`). Die Basisklasse übernimmt Anlaufverzögerung, Aktivierungsprüfung, Ausnahmebehandlung, Rücknahme der Aufruffrequenz und Laufzeitprotokollierung.
Aussage: Das System soll für alle Hintergrunddienste dieselbe Basisklasse verwenden, sodass Aktivierung, Fehlerbehandlung, Frequenzrücknahme und Laufzeitprotokollierung einheitlich sind und ein Dienst nur seine fachliche Aufgabe und sein Intervall festlegt.
Ergebnis: Ein neuer Hintergrunddienst benötigt zwei Überschreibungen; Betriebsverhalten und Überwachbarkeit sind ohne Zusatzaufwand gegeben.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:12-30, 159-179 (Vertrag der Basisklasse) - Begründung: Belegt den minimalen Implementierungsaufwand je Dienst.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/DataQualityService.cs:22 (`: ManagedBackgroundService`) - Begründung: Konkreter Nachweis der Vererbung.
- [PRIMÄR] Intervallwerte in TelemetryFlushService.cs:21, ObjectFulltextIndexUpdateService.cs:51, DocumentFulltextIndexUpdateService.cs:43, ValidateHelpdeskFingerprintService.cs:64, UpdateExpiredProvisionSchemasService.cs:45, UpdateArticleAndMaterialGroupTaxRatesService.cs:75, RefreshIntakeService.cs:31, PlmImportService.cs:64 - Begründung: Belegt die tatsächlich verwendeten Taktungen.
- [KONTEXT] docs/Background Service/DataQualityService.md:23-68 (Regeln für Sitzungsverwaltung, Fehlerbehandlung, Abbruchprüfung) - Begründung: Formuliert die Implementierungsregeln je Aufgabe.
Prüfidee: Jede Klasse in `HostedServices/` außer `ManagedBackgroundService` erbt von dieser und überschreibt `ServiceName` und `GetExecutionInterval`.
Tracelinks: SyRS-035, SyRS-045; StRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-030
Titel: Umschlagtypen und Sichtbarkeitsstruktur der Legacy-Schnittstelle
Ebene: SwRS
Typ: Schnittstelle
Akteur: Legacy-REST-Schnittstelle
Vorbedingung: –
Fakt: Alle Legacy-Methoden verwenden ausschließlich POST und die Umschlagtypen `Request` / `Request<T>` für Eingaben und `Response` / `Response<T>` für Ausgaben; die Nutzdaten liegen im Feld `Data`. Zusätzlich tragen viele Methoden `[Category("…")]` und `[Description("…")]` zur Gruppierung in der eingebauten Hilfeseite (`Centron.Host/HelpPage/`, aktivierbar über `<ActivateHelpPage>` in `WebServiceConfig.xml`). Die Vertragsdefinition ist auf 31 Dateien verteilt (Hauptdatei 358 KB, 30 domänenbezogene Partialdateien), die Implementierung auf 35 Dateien (Hauptdatei 171 KB, DTO-Teil 324 KB). Bekannte Typen für die Serialisierung werden zentral in `KnownTypes.cs` (14 KB) registriert. Es existiert `GetWebServiceMethodList`, das eine Metadatenliste aller Methoden liefert.
Aussage: Das System soll die Legacy-Schnittstelle mit einheitlichen Umschlagtypen, ausschließlich über POST und mit selbstbeschreibenden Metadaten bereitstellen, damit Clients generisch gegen sie programmieren können.
Ergebnis: Ein Client kann jede Methode nach demselben Muster aufrufen; die verfügbaren Methoden sind über `GetWebServiceMethodList` und die Hilfeseite ermittelbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/Services/CentronRestServiceInterfaceParts/ICentronRestService.Receipts.cs:100-138 (`[WebInvoke(Method = "POST", UriTemplate = "…")]`, `Response<T>`/`Request<T>`, `[Category]`, `[Description]`) - Begründung: Repräsentativer Ausschnitt mit allen Merkmalen.
- [PRIMÄR] src/webservice/Centron.Host/Services/KnownTypes.cs - Begründung: Belegt die zentrale Typregistrierung als Voraussetzung der Serialisierung.
- [PRIMÄR] src/webservice/Centron.Host/HelpPage/ und docker/compose/WebServiceConfig.xml (`<ActivateHelpPage>false</ActivateHelpPage>`) - Begründung: Belegt die eingebaute, abschaltbare Selbstbeschreibung.
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetWebServiceMethodList`, ohne `[Authenticate]`) - Begründung: Belegt die maschinenlesbare Methodenliste – und zugleich, dass sie unauthentifiziert abrufbar ist.
- [KONTEXT] docs/reference/architecture/requests-and-responses.md - Begründung: Beschreibt die Umschlagtypen.
Prüfidee: Ein Aufruf von `GetWebServiceMethodList` liefert 2 599 Einträge; jeder Eintrag ist per POST unter `UriTemplate` erreichbar.
Tracelinks: SyRS-010, SyRS-011, SyRS-031; StRS-001
Konsolidierung: Kandidat: Siehe SyRS-031 – Ablösung durch die moderne Schnittstelle.
Status: belegt; Workaround (Die durchgängige Verwendung von POST auch für reine Leseoperationen und die Umschlagtypen sind Artefakte der ursprünglichen WCF-Implementierung und nicht HTTP-konform; im Zielsystem durch ressourcenorientierte Endpunkte zu ersetzen.)
```
```
ID: SwRS-031
Titel: Fassade für Datenzugriff und Fachlogik über die Sitzung
Ebene: SwRS
Typ: funktional
Akteur: Backend
Vorbedingung: Eine Fachoperation wird ausgeführt.
Fakt: Der Datenzugriff läuft über `BLSession`/`DAOSession` mit den Zugriffswegen `GetBL<T>()` (Fachlogikkomponente), `GetGenericDAO<TEntity>()` (generischer Entitätszugriff mit `GetEntity`, `GetEntityList`, `SaveOrUpdate`, `Delete`), `GetDAO<TRepository>()` (spezialisiertes Repository), `GetSession()` (direkter NHibernate-Zugriff mit LINQ), `Session.Advanced.RawSqlAccess` (parametrisiertes Roh-SQL über `ExecuteQuery<T>`, `ExecuteScalarTransactionSave<T>`, `ExecuteNonQueryTransactionSave`) und `Session.Advanced.Cache` (`GetOrAdd`). Transaktionen werden über `Session.WithTransaction(() => …)` bzw. `StartTransaction`/`RollbackTransaction` geklammert. Sitzungen sind kurzlebig und werden mit `using` freigegeben.
Aussage: Das System soll den gesamten Datenzugriff über eine Sitzungsfassade führen, die Fachlogik, generischen Entitätszugriff, spezialisierte Repositories, parametrisiertes Roh-SQL, Zwischenspeicher und Transaktionsklammer an einer Stelle bereitstellt.
Ergebnis: Eine Fachkomponente benötigt keine eigene Verbindungs- oder Transaktionsverwaltung; Roh-SQL ist ausschließlich über die parametrisierte Fassade möglich.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:105-110, 658-662 (`RawSqlAccess.ExecuteQuery<CustomClass>` mit `NamedQueryParameter`) - Begründung: Belegt parametrisiertes Roh-SQL als vorgesehenen Weg.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3544, 3074, 3179, 3206 (`Session.WithTransaction`, `StartTransaction`, `RollbackTransaction`) - Begründung: Belegt die Transaktionsklammer.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7291-7306 (`Session.Advanced.Cache.GetOrAdd` mit parametrisiertem SQL) - Begründung: Belegt die Kombination aus Zwischenspeicher und Roh-SQL.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:42-46, 69-74 (`using (var session = new BLSession())`) - Begründung: Belegt die kurzlebige Sitzungsverwendung.
Prüfidee: Keine Fachkomponente öffnet eine eigene `SqlConnection`; alle SQL-Ausführungen laufen über `Session.Advanced.RawSqlAccess` mit benannten Parametern.
Tracelinks: SyRS-012, SyRS-017, SyRS-033; StRS-001
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-032
Titel: Zeichenkettenverkettung in generierten SQL-Anweisungen der Nummernvergabe
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `NumberGroupBL`
Vorbedingung: Eine neue Nummer wird aus einem Nummernkreis ermittelt.
Fakt: `NumberGroupBL.FindNextNumber` erzeugt seine Prüfabfragen durch Zeichenkettenverkettung statt über Parameter: `$"SELECT COUNT(*) AS cnt FROM {tableName} WHERE {fieldName} = '{counter}'"` bzw. `… = {counter}` sowie `$"SELECT COUNT(*) AS cnt FROM dbo.Kunden WHERE I3D = {counter}"`. Die eingesetzten Werte stammen aus `numberGroup.GetTableName()`, `numberGroup.GetFieldName()` (beide aus der Aufzählung `NumberGroupEnum` abgeleitet, nicht aus Benutzereingaben) und `counter` (Ganzzahl). Im übrigen Code wird dagegen konsequent parametrisiert gearbeitet (`NamedQueryParameter`, `AddParameter`).
Aussage: Das System soll alle SQL-Anweisungen parametrisiert erzeugen; die Verkettung von Werten in Anweisungstexte ist auch dann zu vermeiden, wenn die Werte derzeit aus vertrauenswürdigen Quellen stammen.
Ergebnis: Kein SQL-Anweisungstext enthält interpolierte Werte; Tabellen- und Spaltennamen stammen aus einer Positivliste.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:107-131 (drei interpolierte SQL-Anweisungen) - Begründung: Belegt die Abweichung vom sonst durchgängigen Parametrisierungsmuster.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7295-7305 (parametrisierte Alternative im selben Projekt: `f.AddParameter("CustomerI3D", customerI3D)`) - Begründung: Belegt, dass das sichere Muster verfügbar ist und andernorts verwendet wird.
- [KONTEXT] docs/reference/database/script-rules.md:135-138 („When direct SQL is needed, ensure proper schema references and SQL injection protection") - Begründung: Formuliert die Regel als Projektvorgabe, die hier nicht eingehalten ist.
Prüfidee: Eine statische Codeanalyse auf interpolierte SQL-Zeichenketten meldet die drei Stellen in `NumberGroupBL`; nach Umstellung auf Parameter meldet sie keine.
Tracelinks: SyRS-018; StRS-005
Konsolidierung: nein
Status: belegt; Workaround (Die derzeitigen Eingangswerte – Aufzählungswerte und Ganzzahlen – sind nicht angreifbar; die Konstruktion widerspricht jedoch der projekteigenen Regel und ist bei künftigen Erweiterungen der Aufzählung ein Risiko.)
```
```
ID: SwRS-033
Titel: Skriptbasierte, idempotente Schemafortschreibung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `ScriptEngineBL`
Vorbedingung: Der Web-Service startet.
Fakt: Die Schemafortschreibung besteht aus `ScriptEngineBL`, `ScriptMethodPool`, `ScriptMethodKind`, `ScriptSpecialObjects`, `ScriptHelpers`, den Basisklassen `BaseScriptMethod` und `BaseRecurringScriptMethod` sowie den Schnittstellen `IScriptMethod` und `IRecurringScriptMethod`. Es existieren 764 einmalige Skripte `ScriptMethod{Nummer}.cs`; die Nummernvergabe erfolgt laut Projektdokumentation über eine externe Excel-Liste. `BaseRecurringScriptMethod` erlaubt zusätzlich wiederkehrend auszuführende Skripte, die vom Hintergrunddienst `RecurringScriptService` gestartet werden. `ScriptHelpers` erzeugt bedingte DDL-Anweisungen; für indizierte Spalten existiert `AlterColumnTypeIndexSafe`.
Aussage: Das System soll Schemaänderungen als nummerierte, unabhängige und wiederholbar ausführbare Skripte führen und zwischen einmalig und wiederkehrend auszuführenden Skripten unterscheiden.
Ergebnis: Eine Datenbank beliebigen Ausgangsstands erreicht nach dem Start den aktuellen Strukturstand; eine erneute Ausführung ändert nichts.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs, ScriptMethods/ScriptMethodPool.cs, ScriptMethods/BaseScriptMethod.cs, BaseRecurringScriptMethod.cs, IScriptMethod.cs, IRecurringScriptMethod.cs, ScriptHelpers.cs, ScriptMethodKind.cs, ScriptSpecialObjects.cs - Begründung: Vollständige Komponentenmenge des Mechanismus.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/ (764 Dateien) - Begründung: Umfang der Schemahistorie.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/RecurringScriptService.cs - Begründung: Belegt die wiederkehrende Skriptausführung als eigenen Dienst.
- [KONTEXT] docs/reference/database/script-rules.md:7-58, 129-141 - Begründung: Beschreibt Ablage, Nummernvergabe, Hilfsmethoden und Idempotenzregel.
Prüfidee: Alle 764 Skriptdateien enthalten ausschließlich bedingte DDL-Anweisungen bzw. `ScriptHelpers`-Aufrufe; eine zweite Ausführung erzeugt keine Änderung.
Tracelinks: SyRS-039; StRS-019
Konsolidierung: nein
Status: belegt; Workaround (Die Skriptnummernvergabe erfolgt über eine repository-externe Excel-Liste; damit ist die Eindeutigkeit nicht durch das Versionsverwaltungssystem gesichert.)
```
```
ID: SwRS-034
Titel: Zweistufige Serverkonfiguration aus Datei und Datenbank
Ebene: SwRS
Typ: Daten
Akteur: Web-Service
Vorbedingung: –
Fakt: Die Serverkonfiguration ist auf zwei Orte verteilt: (a) die Datei `WebServiceConfig.xml`, gelesen über `WebServiceConfigHelper.Current`, mit den Feldern `WebServiceAddress`, `PublicWebServiceAddress`, `WebServiceCertificateFilePath`, `WebServiceCertificatePassword`, `ActiveDirectoryAuthEnabled`, `ActiveDirectoryUrl`, `ActiveDirectoryName`, `ActiveDirectoryCertificateHash`, `DatabaseConnectionString`, `DatabaseConnectionStringPlain`, `UseIncreasedThreadPool`, `ActivateHelpPage`, `ExecuteServices`, `Proxy*`, `TwoFactorAuthEnabled`, `TwoFactorAuthType`, `RadiusServer*`, `MailTwoFactorAuth*`, `TwoFactorValidDurationInDays`, `SecretKey`; (b) die Datenbanktabellen `ApplicationSettings` und `Stammdat`. Startparameter (Adresse, Zertifikat, Datenbankverbindung, Authentifizierungsverfahren, Dienstausführung) liegen in der Datei, fachliche Einstellungen in der Datenbank. Für Docker wird die Datei als Volume eingebunden.
Aussage: Das System soll startrelevante und sicherheitsrelevante Parameter in einer Konfigurationsdatei und alle fachlichen Einstellungen in der Datenbank führen, sodass die Datenbank ohne Dateizugriff fachlich konfigurierbar bleibt.
Ergebnis: Ein Wechsel des Authentifizierungsverfahrens auf Systemebene erfordert eine Dateiänderung und einen Neustart; eine fachliche Einstellungsänderung wirkt ohne Neustart.
Belege:
- [PRIMÄR] docker/compose/WebServiceConfig.xml (vollständige Feldliste) - Begründung: Belegt Inhalt und Umfang der Dateikonfiguration.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:36 (`WebServiceConfigHelper.Current.ActiveDirectoryAuthEnabled`) und TwoFactorAuthBL.cs:41, 103, 185 - Begründung: Belegt die Auswertung der Dateikonfiguration im Sicherheitspfad.
- [PRIMÄR] docker/compose/compose.yaml (`volumes: - ./WebServiceConfig.xml:/app/WebServiceConfig.xml`) - Begründung: Belegt die Einbindung der Datei im Containerbetrieb.
- [PRIMÄR] src/webservice/c-entron.misc.ConnectionManager/ - Begründung: Belegt das Werkzeug zur Erzeugung der Datei.
Prüfidee: Eine Änderung an `TwoFactorAuthEnabled` wirkt erst nach Neustart; eine Änderung an `IsZugferdInvoiceActive` wirkt sofort.
Tracelinks: SyRS-040, SyRS-041, SyRS-049; StRS-019, StRS-024
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-035
Titel: Zentrale Build- und Versionierungsvorgaben
Ebene: SwRS
Typ: nicht-funktional (Wartbarkeit – Modifizierbarkeit)
Akteur: Build-Prozess
Vorbedingung: –
Fakt: `Directory.Build.props` setzt für alle Projekte gemeinsam: eingebettete Debugsymbole (`DebugType = embedded`), `TreatWarningsAsErrors = true` mit zentraler Ausnahmeliste, Herstellerangaben (`Company = NEXOWARE Systems GmbH`, `Product = NEXOWARE c-entron ERP`, `Copyright … 2012 - 2026`), einen Platzhalter für die Git-Commit-Kennung in `InformationalVersion` und die Kennzeichnung von Entwicklerbuilds (`IsDevBuild` → Präfix „Dev-Build", Definition `DEV_BUILD`). Die DevExpress-Version wird zentral über `DevExpress.Version.props` gesetzt und mit `src/nexus/Directory.Build.props` geteilt. `global.json` legt das .NET-SDK auf `10.0.100` mit `rollForward: latestFeature` fest. `version.json` (Nerdbank.GitVersioning) definiert die Version `2.0.2611-alpha`, Release-Zweige nach dem Muster `release/v{version}` und `versionIncrement: build`.
Aussage: Das System soll Übersetzungs-, Versionierungs- und Abhängigkeitsvorgaben zentral und für alle Projekte gemeinsam festlegen und Produktivbauten von Entwicklerbauten in der Versionsangabe unterscheidbar machen.
Ergebnis: Jede erzeugte Assembly trägt Herstellerangabe, Version, Git-Commit-Kennung und – bei Entwicklerbauten – eine entsprechende Kennzeichnung.
Belege:
- [PRIMÄR] Directory.Build.props:1-50 (alle genannten Eigenschaften) - Begründung: Zentrale, für alle Projekte wirksame Vorgabe.
- [PRIMÄR] global.json (SDK 10.0.100) - Begründung: Bindet den Build an eine definierte SDK-Version.
- [PRIMÄR] version.json (Nerdbank.GitVersioning, `2.0.2611-alpha`, Release-Zweigmuster) - Begründung: Belegt die automatisierte, git-basierte Versionsvergabe.
- [PRIMÄR] DevExpress.Version.props - Begründung: Belegt die zentrale Steuerung der Fremdkomponentenversion.
- [KONTEXT] docs/operations/build-server-and-automated-builds.md, docs/operations/update-devexpress.md, docs/operations/release-stop.md - Begründung: Beschreiben Buildbetrieb, Fremdkomponenten-Aktualisierung und Release-Prozess.
Prüfidee: Eine lokal erzeugte Assembly trägt in `InformationalVersion` das Präfix „Dev-Build"; eine Build-Server-Assembly trägt stattdessen die Commit-Kennung.
Tracelinks: SyRS-043, SyRS-044; StRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-036
Titel: MVVM-Struktur des Windows-Fachclients
Ebene: SwRS
Typ: funktional
Akteur: Windows-Fachclient
Vorbedingung: –
Fakt: Der Client umfasst 1 233 XAML-Dateien. Die Struktur trennt `Views/`, `ViewModels/`, `Modules/`, `Dialogs/`, `Wizards/`, `Behaviors/`, `Converters/` (in `Centron.Controls`), `Managers/`, `Services/`, `Style/`, `Resources/`, `Localization/`. Wiederverwendbare Oberflächenbausteine liegen in `Centron.Controls` (u. a. `PositionGrid`, `Checklist`, `FileViewer`, `PdfScanning`, `ProductMatrix`, `TaskManagement`, `Telephony`, `Wizard`, `ExcelExport`, `MailTemplates`). Das Basisframework `Centron.WPF.UI.Extension` stellt `Mvvm/`, `Commands/`, `Behaviors/`, `ValueConverter/`, `Extensibility/`, `Messages/`, `UiProperties/` bereit. Oberflächenbindungen nutzen `ObservableCollection<T>`, `INotifyPropertyChanged` und `DelegateCommand`. Dialoge laufen über `CentronApplication.Instance.DialogManager` (`ShowInputDialog`, `ShowConfirmationDialog`, `ShowDialog`).
Aussage: Das System soll die Oberfläche des Fachclients nach dem MVVM-Muster mit zentralem Dialogdienst, wiederverwendbaren Steuerelementen und einem gemeinsamen Basisframework aufbauen; Fachlogik soll nicht in Ansichten oder Code-Behind liegen.
Ergebnis: Eine Ansicht enthält ausschließlich Darstellungs- und Bindungsangaben; Fachentscheidungen liegen im ViewModel oder in der Fachlogikschicht.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/ (Ordner `Views`, `ViewModels`, `Modules`, `Dialogs`, `Wizards`, `Behaviors`, `Managers`, `Services`, `Style`, `Localization`) und src/centron/Centron.WPF.UI.Extension/Mvvm/, Commands/ - Begründung: Belegt die Strukturtrennung unmittelbar.
- [PRIMÄR] src/shared/Centron.Controls/ (36 fachliche Steuerelementbereiche) - Begründung: Belegt die Wiederverwendung von Oberflächenbausteinen zwischen Anwendungen.
- [KONTEXT] docs/reference/architecture/mvvm-in-centron.md, docs/guides/ui/create-module.md, create-dialog.md, create-settings-page.md - Begründung: Beschreiben Muster und Vorgehen für neue Ansichten, Module und Dialoge.
- [KONTEXT] docs/features/automatic-helpdesk-creation-templates.md:194-225, 521-546 (ViewModel-Aufbau, Dialogdienstverwendung) - Begründung: Konkretes Umsetzungsbeispiel des Musters.
Prüfidee: Stichprobe von 10 Ansichten: keine enthält Datenbank- oder Fachlogikzugriffe im Code-Behind; alle Aktionen laufen über `DelegateCommand`.
Tracelinks: SyRS-032; StRS-001, StRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-037
Titel: Telemetrieerhebung und -übertragung
Ebene: SwRS
Typ: Daten
Akteur: Web-Service
Vorbedingung: –
Fakt: Es existieren der Fachbereich `src/backend/Centron.BL/Telemetry/` (12 Entitätsdateien unter `Centron.Entities/Entities/Telemetry`, u. a. `TelemetryLicenseKind`) sowie die Hintergrunddienste `TelemetryFlushService` (Intervall 1 Minute) und `TelemetryUploadService` (12 KB) und `FlushAnalyticEventsService`. `LicenseGuids.cs` trägt den Klassenkommentar „Task: Update TelemetryLicenseKind.cs (in Centron.Data.Entities.Telemetry namespace) enum, when new licenses were added.", was die Kopplung von Telemetrie und Lizenzbestand belegt.
Aussage: [HYPOTHESE] Das System soll Nutzungs- und Betriebsdaten erheben und an den Hersteller übertragen; Art, Umfang, Rechtsgrundlage und Abschaltbarkeit dieser Übertragung sind festzulegen und gegenüber dem Anwenderunternehmen transparent zu machen.
Ergebnis: Der Anwender kennt Umfang und Zweck der übertragenen Daten und kann die Übertragung steuern.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryUploadService.cs (12 KB), TelemetryFlushService.cs, FlushAnalyticEventsService.cs - Begründung: Belegt Erhebung und Übertragung als aktive Systemfunktion.
- [PRIMÄR] src/backend/Centron.BL/Telemetry/ und src/backend/Centron.Entities/Entities/Telemetry/ (12 Dateien) - Begründung: Belegt das Telemetriedatenmodell.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs:7 (Klassenkommentar zur Pflege von `TelemetryLicenseKind`) - Begründung: Belegt die Kopplung an den Lizenzbestand.
Prüfidee: Auswertung des Datenumfangs von `TelemetryUploadService` und Abgleich mit der Datenschutzerklärung gegenüber dem Anwenderunternehmen.
Tracelinks: SyRS-035; StRS-013, StRS-025
Konsolidierung: nein
Status: HYPOTHESE
Fehlende Information: Der Inhalt der übertragenen Telemetriedaten wurde in dieser Iteration nicht ausgelesen (`TelemetryUploadService.cs` und die zwölf Telemetrieentitäten wurden nicht im Detail analysiert). Ohne diese Analyse lässt sich weder der Personenbezug noch die Abschaltbarkeit beurteilen. Nachschlag in einer Folge-Iteration erforderlich; siehe `Analysebericht.md`.
```
```
ID: SwRS-038
Titel: Zwischenspeicherung häufig gelesener Stammdaten
Ebene: SwRS
Typ: nicht-funktional (Performance-Effizienz)
Akteur: Backend
Vorbedingung: –
Fakt: Es existiert die Komponente `CachedTableBL` (100 KB) sowie der Hintergrunddienst `CacheUpdateService`, der eine optimierte Aktualisierung frühestens alle 60 Sekunden ausführt (`if (_lastOptimizedUpdate == null || DateTime.Now - _lastOptimizedUpdate > TimeSpan.FromMinutes(1))`). Ergänzend nutzen einzelne Komponenten den sitzungsgebundenen Zwischenspeicher `Session.Advanced.Cache.GetOrAdd(schlüssel, factory)`, belegt für Benutzerrechte (`AllRightsFromAppUser{I3D}`), Web-Account-Rechte, das ZUGFeRD-Format (`GetZugferdFormatInternal{…}`) und Kunden-Konzernzuordnungen (`GetCompanyGroupCustomerI3DForReceiptData_{I3D}`). Im Client existiert `CentronCache.Instance` mit Feldern wie `CurrentUserAppRights` und `CrmSettings`.
Aussage: Das System soll häufig gelesene Stammdaten und Rechteinformationen auf Server- und Clientseite zwischenspeichern, die Zwischenspeicher zeitgesteuert aktualisieren und je Sitzung eine konsistente Sicht liefern.
Ergebnis: Wiederholte Lesezugriffe auf Stammdaten und Rechte erzeugen innerhalb der Gültigkeitsdauer keinen zusätzlichen Datenbankzugriff.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Services/CachedTableBL.cs (100 KB) und src/webservice/Centron.Host/AspNetCore/HostedServices/CacheUpdateService.cs:30 - Begründung: Belegt serverseitige Zwischenspeicherung und deren Aktualisierungstakt.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:646, 674 - Begründung: Belegt sitzungsgebundene Zwischenspeicherung von Rechten.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:87 und src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7291 - Begründung: Belegt weitere Anwendungsfälle.
- [KONTEXT] docs/guides/development/check-userrights.md:12 (`CentronCache.Instance.CurrentUserAppRights`) - Begründung: Belegt den clientseitigen Rechtezwischenspeicher.
Prüfidee: Nach Entzug eines Rechts wirkt die Änderung im Client spätestens nach Neuanmeldung; serverseitig spätestens nach Ablauf der Sitzung.
Tracelinks: SyRS-012, SyRS-038; StRS-002
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-039
Titel: Umfang und Verteilung des persistenten Datenmodells
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: –
Fakt: Das Datenmodell umfasst 1 179 Entitätsdateien in `src/backend/Centron.Entities/Entities/` und 983 FluentNHibernate-Zuordnungsdateien in `src/backend/Centron.DAO/Mappings/`, deren Ordnerstruktur die Domänenstruktur der Entitäten spiegelt. Die größten Domänen sind Sales (327 Entitätsdateien), Warehousing (103), Administration (98), CustomerArea (89), Accounts (54), DbEntities (39, temporäre Legacy-Entitäten), Statistics (35). Die NHibernate-Konfiguration liegt unter `Centron.DAO/NHibernateConfiguration/`, benutzerdefinierte Typen unter `UserTypes/`, benannte Abfragen unter `NamedQueries/`, Repositories unter `Repositories/`. Verwendete Fassung: NHibernate 5.6.0.
Aussage: Das System soll für jede persistierte Entität eine eigene, explizite Zuordnungsklasse führen, die in derselben Domänenstruktur wie die Entität abgelegt ist.
Ergebnis: Zu jeder mit NHibernate persistierten Entität ist die Zuordnungsdatei über den Domänenpfad auffindbar.
Belege:
- [PRIMÄR] Auszählung: src/backend/Centron.Entities/Entities/ = 1 179 `.cs`, src/backend/Centron.DAO/Mappings/ = 983 `.cs` - Begründung: Quantifiziert Umfang und Zuordnungsgrad objektiv.
- [PRIMÄR] src/backend/Centron.DAO/Centron.DAO.csproj (`<PackageReference Include="NHibernate" Version="5.6.0" />`) - Begründung: Belegt die eingesetzte Persistenzfassung.
- [PRIMÄR] src/backend/Centron.DAO/ (Unterordner `Mappings`, `NHibernateConfiguration`, `UserTypes`, `NamedQueries`, `Repositories`, `AdoNETDataAccess`, `CustomDAOs`) - Begründung: Belegt die Binnenstruktur der Persistenzschicht.
- [KONTEXT] docs/getting-started/ai-codebase-navigation.md:35-36 - Begründung: Bestätigt die Spiegelung der Domänenstruktur.
Prüfidee: Für eine Stichprobe von 20 Entitäten existiert im entsprechenden Unterordner von `Mappings/` eine Zuordnungsklasse `{Entität}Maps`.
Tracelinks: SyRS-039; StRS-001, StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-040
Titel: Getrenntes Rechtemodell für Portalkonten
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `AppRightsBL` / `WebAccount`
Vorbedingung: Ein Portalkonto führt eine Aktion aus.
Fakt: Portalkonten (`WebAccount`) besitzen ein vom Mitarbeiterrechtemodell vollständig getrenntes Rechtemodell: Die Rechte liegen in der Tabelle `WebAccountsRights` (Spalten `WebAccountsI3D`, `WebRightsI3D`) und werden über `AppRightsBL.CheckWebRightsFromUser` bzw. `HasWebAccountRight` aufgelöst. Die Rechtekonstanten liegen in der Aufzählung `WebAccountRightsConst` (belegt: `WEBRIGHT_CREATEREQUEST`, `WEBRIGHT_EDITALLREQUESTS`). Es existiert keine Gruppenzwischenstufe – Rechte werden dem Konto direkt zugeordnet. Die Fachlogik verzweigt über `LoggedInUser.IsWebAccountLogin` (`HelpdeskBL.CheckRights`, `ReceiptBL.CanUserViewReceipt`). Die Verwaltung erfolgt über das Recht `WEBACCOUNT_MANAGEMENT = 20800162`; die Portalsichtbarkeit steuert zusätzlich `WebRightsVisibility`.
Aussage: Das System soll für externe Portalkonten ein eigenes, direkt kontobezogenes Rechtemodell führen, das vom Mitarbeiterrechtemodell getrennt ist, sodass interne Rechte niemals über ein Portalkonto wirksam werden können.
Ergebnis: Ein Portalkonto kann kein Mitarbeiterrecht besitzen; Fachfunktionen prüfen anhand von `IsWebAccountLogin`, welches Rechtemodell anzuwenden ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:113-130, 666-691 (`CheckWebRightsFromUser`, `HasWebAccountRight`, SQL über `WebAccountsRights`) - Begründung: Belegt das getrennte Datenmodell und dessen Auflösung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-415, 468-479 (Verzweigung über `IsWebAccountLogin`, `WebAccountRightsConst`) - Begründung: Belegt die Trennung in der Fachlogik.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (harte Ablehnung für Web-Benutzer) - Begründung: Belegt die Abschottung des internen Belegwesens.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebRightsVisibility.cs - Begründung: Belegt eine eigene Komponente für die Portalsichtbarkeit.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2391-2394 (`WEBACCOUNT_MANAGEMENT`) - Begründung: Belegt die Verwaltung der Portalkonten als eigenes Mitarbeiterrecht.
Prüfidee: Ein Portalkonto kann über keine Konfiguration ein Recht aus `UserRightsConst` erhalten; der Versuch, über die Portalanmeldung einen Beleg abzurufen, wird abgelehnt.
Tracelinks: SyRS-006, SyRS-026; StRS-002, StRS-011
Konsolidierung: Kandidat: Zwei getrennte Rechtemodelle (gruppenbasiert für Mitarbeiter, direkt für Portalkonten) und zwei getrennte Kennwortprüfungen (SwRS-026); im Zielsystem als ein Identitäts- und Autorisierungsdienst mit Mandantentrennung zusammenführbar.
Status: belegt
```
@@ -0,0 +1,160 @@
# Traceability-Matrix
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
**Umfang:** 114 Anforderungen (25 StRS, 49 SyRS, 40 SwRS), 421 Artefaktbelege (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`)
Die Spalte **Artefaktbeleg** nennt je Zeile den `PRIMÄR`-Beleg mit der höchsten Aussagekraft für die Anforderungskette. Die vollständigen Belege stehen in `StRS.md`, `SyRS.md` und `SwRS.md`. Beide Matrizen wurden maschinell aus den `Tracelinks`-Feldern der drei Spezifikationsdateien erzeugt.
---
## 1. Konsolidierte Matrix (StRS über SyRS zu SwRS)
Eine Zeile je SyRS-Anforderung. Die StRS-Spalte enthält alle Stakeholder-Anforderungen, die diese Systemanforderung begründen; die SwRS-Spalte alle Softwareanforderungen, die sie umsetzen.
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg |
|---|---|---|---|
| StRS-022 | SyRS-001 Auswahl Authentifizierungsverfahren | SwRS-025 | `src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:54-146` |
| StRS-022 | SyRS-002 Rückfallverfahren abweichender Auth-Art | SwRS-025 | `Auth/AuthenticatorFactory.cs:57-86, 203-207` (`AppUser.AuthentificationKind`) |
| StRS-002, StRS-022 | SyRS-003 Sperrprüfung Benutzerkonto | SwRS-025, SwRS-026 | `Auth/Authenticator.cs:157-218` (`ValidateAppUser`) |
| StRS-022 | SyRS-004 Sitzungsticket mit Gültigkeitsdauer | SwRS-026 | `Administration/Logins/TicketBL.cs:26-28, 136-170` |
| StRS-004, StRS-022 | SyRS-005 Wiederverwendung Sitzungstickets | SwRS-005 | `Auth/Authenticator.cs:124-140` |
| StRS-002, StRS-004 | SyRS-006 Anmeldeverbot/-voraussetzung je Anwendungsart | SwRS-005, SwRS-025, SwRS-040 | `Auth/Authenticator.cs:68-86`; `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| StRS-004 | SyRS-007 Lizenzprüfung Version/Nutzungsobergrenze | SwRS-005 | `Administration/Licensing/LicenseManager.cs:258-302` |
| StRS-004, StRS-019 | SyRS-008 Betrieb ohne Lizenzserververbindung | SwRS-005 | `LicenseManager.cs:47-68, 117-139` (`FileLicenseCache`, `FakeOfficeClient`) |
| StRS-002, StRS-017 | SyRS-009 Rechteprüfung moderne REST-Schnittstelle | SwRS-002 | `Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs:29-56` |
| StRS-002, StRS-023 | SyRS-010 Authentifizierungspflicht Legacy-REST | SwRS-027, SwRS-030 | `Centron.WebServices.Core/Interception/Interceptors/AuthenticateAttribute.cs`; Auszählung 2 599 / 2 374 |
| StRS-002, StRS-023 | **SyRS-011 [HYPOTHESE]** 221 nicht attributierte Endpunkte | SwRS-030 | `Centron.Host/Services/ICentronRestService.cs` (`DeleteLogo`, `SaveCustomerSpecialArticle` ohne `[Authenticate]`) |
| StRS-002 | SyRS-012 Rechteprüfung mit Zwischenspeicherung | SwRS-003, SwRS-031, SwRS-038 | `Administration/Rights/AppRightsBL.cs:644-664` |
| StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 | SyRS-013 Einschränkende Rechte als Sichtbarkeitsfilter | SwRS-003, SwRS-020, SwRS-021 | `Sales/Support/HelpdeskBL.cs:269-291` (`ShowHelpdeskRight`) |
| StRS-002 | SyRS-014 Schutz der Administratorgruppe | SwRS-002, SwRS-003 | `AppRightsBL.cs:348-374, 714-759` |
| StRS-001, StRS-004 | SyRS-015 Modulsichtbarkeit als Recht UND Lizenz | SwRS-005 | `Centron.WPF.UI/Modules/ModuleRegistration.cs:421-448` |
| StRS-005, StRS-014 | SyRS-016 Belegzustandsmodell (drei Zustände) | SwRS-004, SwRS-006 | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28` |
| StRS-005, StRS-014, StRS-015 | SyRS-017 Validierung beim Speichern eines Belegs | SwRS-006, SwRS-007, SwRS-008, SwRS-009, SwRS-010, SwRS-013, SwRS-019, SwRS-031 | `Sales/Receipts/ReceiptBL.cs:3544-3868` |
| StRS-003, StRS-005 | SyRS-018 Belegnummernvergabe filialbezogen | SwRS-007, SwRS-009, SwRS-014, SwRS-032 | `Administration/Company/NumberGroupBL.cs:62-134` |
| StRS-005, StRS-014 | SyRS-019 Belegsperre bei gleichzeitiger Bearbeitung | SwRS-006 | `ReceiptBL.cs:3085-3096, 3160-3175` |
| StRS-005, StRS-008, StRS-014 | SyRS-020 Sperre Rückversionierung (Seriennr./Weiterverarbeitung) | SwRS-006 | `ReceiptBL.cs:3103-3115` |
| StRS-002, StRS-005, StRS-015 | SyRS-021 Mindestpreisprüfung mit Zweitanmeldung | SwRS-009, SwRS-013, SwRS-019 | `ReceiptBL.cs:9036-9124` |
| StRS-005 | SyRS-022 Beleg-Muster mit negativer Nummer | SwRS-006 | `Centron.Entities/.../ReceiptBase.cs:65`; `ReceiptBL.cs:3586-3593, 7280-7284` |
| StRS-005, StRS-006 | SyRS-023 Automatischer Belegabschluss | SwRS-006, SwRS-009 | `ReceiptBL.cs:9753-9763, 3815-3817` |
| StRS-005, StRS-010 | SyRS-024 Prüfung doppelter externer Nummern | SwRS-006 | `ReceiptBL.cs:3703, 3746` |
| StRS-002, StRS-008 | SyRS-025 Negative Lagerbuchung nur mit Recht | SwRS-009, SwRS-011, SwRS-013 | `Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:347-405` |
| StRS-002, StRS-007, StRS-011 | SyRS-026 Rechteprüfung bei Tickets | SwRS-010, SwRS-011, SwRS-012, SwRS-040 | `Sales/Support/HelpdeskBL.cs:410-479` |
| StRS-007 | SyRS-027 Feldlängenbegrenzung Tickettexte | SwRS-010, SwRS-011 | `HelpdeskBL.cs:328-349` |
| StRS-013 | SyRS-028 DSGVO-Anonymisierung statt Löschung | SwRS-016 | `Administration/DataSecurity/DataSecurityBL.cs:787-789, 1195-1284` |
| StRS-006, StRS-021 | SyRS-029 Abbruch Vertragsrechnung ohne Nutzungsdaten | SwRS-009, SwRS-014 | `WebServices/.../AutomaticFacturaWebServiceBL.cs:721-726, 795-802, 2412` |
| StRS-012 | SyRS-030 Profilabhängige E-Rechnungserzeugung | SwRS-015 | `DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:85-231` |
| StRS-001 | SyRS-031 Zwei parallele Server-Schnittstellen | SwRS-030 | `Centron.Host/Services/ICentronRestService*.cs` (2 599) gegenüber `Centron.Controllers/Controllers/` (160) |
| StRS-001, StRS-019 | SyRS-032 Dualer Client-Datenzugriff (BL/WS) | SwRS-001, SwRS-031, SwRS-036 | `Centron.WPF.UI/Services/Logics/**/{I,BL,WS}*Logic.cs` |
| StRS-001 | SyRS-033 Einheitliches Ergebnisobjekt `Result<T>` | SwRS-001, SwRS-031 | `Auth/Authenticator.cs:68-107`; `ReceiptBL.cs:3544-3868` |
| StRS-009, StRS-020, StRS-021 | SyRS-034 Externe Fachdienste in Integrationsbibliotheken | SwRS-015, SwRS-024 | `src/apis/` (7 Projekte); `Centron.Controllers/Controllers/v1/Integrations/` |
| StRS-025 | SyRS-035 Fehlertoleranter Hintergrundbetrieb | SwRS-023, SwRS-029, SwRS-037 | `Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-157` |
| StRS-014, StRS-019 | SyRS-036 Ereignisprotokollierung (Schwelle, Rotation) | SwRS-032 | `CentronNexus.Host/appsettings.json` (Abschnitt `NLog`) |
| StRS-011, StRS-024 | SyRS-037 Begrenzung Dateiuploads Portal | SwRS-034 | `CentronNexus.Host/appsettings.json` (`Upload.Max*UploadSizeInMb`) |
| StRS-011, StRS-019 | SyRS-038 Begrenzung Ticket-Zwischenspeicher | SwRS-038 | `CentronNexus.Host/appsettings.json` (`TicketCache.CachedMonths` / `MaxClosedTickets`) |
| StRS-004, StRS-019 | SyRS-039 Automatische DB-Strukturaktualisierung | SwRS-018, SwRS-033, SwRS-039 | `Centron.BL/Administration/Scripts/ScriptMethods/Scripts/` (764 Skripte) |
| StRS-019 | SyRS-040 Verschlüsselte DB-Verbindungszeichenfolge | SwRS-023, SwRS-034 | `docker/compose/WebServiceConfig.xml` |
| StRS-019 | **SyRS-041 [HYPOTHESE]** Transportverschlüsselung (HTTPS) | SwRS-034 | `docker/compose/WebServiceConfig.xml`; `CentronNexus.Host/appsettings.json` (`Host.Url` = HTTP) |
| StRS-019 | **SyRS-042 [HYPOTHESE]** Schutz vor E-Mail-Versand in DEBUG-Builds | SwRS-035 | `docker/compose/compose.yaml` (Dienst `smtp` / Mailcatcher) |
| StRS-019 | SyRS-043 Warnungen als Fehler; Paketschwachstellen ausgenommen | SwRS-035 | `Directory.Build.props:11, 22-25` |
| StRS-005, StRS-014 | SyRS-044 Automatisierte Testabdeckung (12 Testprojekte) | SwRS-035 | `tests/` (12 Projekte, 378 `.cs`) |
| StRS-001, StRS-025 | SyRS-045 Volltextindizierung | SwRS-029 | `HostedServices/ObjectFulltextIndexUpdateService.cs:51`; `Centron.BL/IndexSearch/` |
| StRS-014 | SyRS-046 Feldgenaue Änderungsprotokollierung | SwRS-017 | `Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-142` |
| StRS-002, StRS-014 | SyRS-047 Protokollierung Rechteänderungen | SwRS-002, SwRS-003 | `AppRightsBL.cs:762-857` (`AppRightLog`) |
| StRS-018 | SyRS-048 Deutsche Standardsprache, englische Zweitfassung | SwRS-022, SwRS-036 | `Centron.WPF.UI/Resources/LocalizedStrings.resx` (404 KB) / `.en.resx` (349 KB) |
| StRS-024 | SyRS-049 Zentrale typisierte Anwendungseinstellungen | SwRS-028, SwRS-034 | `Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs` (492 Einträge) |
---
## 2. Rückwärts-Traceability (SwRS über SyRS zu StRS)
Spalte **verknüpfte SyRS** enthält die Vereinigung aus Vorwärts- und Rückwärtsverweisen; Spalte **erreichbare StRS** die daraus über die SyRS-Ebene erreichbaren Stakeholder-Anforderungen.
| SwRS-ID | Titel | verknüpfte SyRS | erreichbare StRS |
|---|---|---|---|
| SwRS-001 | Sechsschichtige Anwendungsarchitektur | SyRS-032, SyRS-033 | StRS-001, StRS-019 |
| SwRS-002 | Datenmodell der Zugriffsberechtigungen | SyRS-009, SyRS-014, SyRS-047 | StRS-002, StRS-014, StRS-017 |
| SwRS-003 | Wiederherstellbare Standardrechtestruktur | SyRS-012, SyRS-013, SyRS-014, SyRS-047 | StRS-002, StRS-003, StRS-007, StRS-014, StRS-016, StRS-017 |
| SwRS-004 | Objektartschlüssel als systemweiter Verweismechanismus | SyRS-016 | StRS-005, StRS-014 |
| SwRS-005 | Lizenzkomponente als Singleton | SyRS-005, SyRS-006, SyRS-007, SyRS-008, SyRS-015 | StRS-001, StRS-002, StRS-004, StRS-011, StRS-019, StRS-022 |
| SwRS-006 | Vererbungsstruktur der Belegentitäten | SyRS-016, SyRS-017, SyRS-019, SyRS-020, SyRS-022, SyRS-023, SyRS-024 | StRS-005, StRS-006, StRS-008, StRS-010, StRS-014, StRS-015 |
| SwRS-007 | Zweigleisige Belegpersistenz | SyRS-017, SyRS-018 | StRS-003, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-008 | Versionstabellen als strukturgleiche Kopien | SyRS-017 | StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-009 | Delegation belegartspezifischer Logik | SyRS-017, SyRS-018, SyRS-021, SyRS-023, SyRS-025, SyRS-029 | StRS-002, StRS-003, StRS-005, StRS-006, StRS-008, StRS-014, StRS-015, StRS-021 |
| SwRS-010 | **[HYPOTHESE]** Reflexionsbasierte Auflösung | SyRS-017, SyRS-026, SyRS-027 | StRS-002, StRS-005, StRS-007, StRS-008, StRS-011, StRS-014, StRS-015 |
| SwRS-011 | Komponentenschnitt Ticketverarbeitung | SyRS-025, SyRS-026, SyRS-027 | StRS-002, StRS-007, StRS-008, StRS-011 |
| SwRS-012 | Konfigurierbare Ticketzustände | SyRS-026 | StRS-002, StRS-007, StRS-011 |
| SwRS-013 | Komponentenschnitt Belegpreis/-position | SyRS-017, SyRS-021, SyRS-025 | StRS-002, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-014 | Verteilung der Vertragsabrechnung | SyRS-018, SyRS-029 | StRS-003, StRS-005, StRS-006, StRS-021 |
| SwRS-015 | Kapselung E-Rechnungserzeugung | SyRS-030, SyRS-034 | StRS-009, StRS-010, StRS-012, StRS-020, StRS-021 |
| SwRS-016 | Anonymisierungskomponente mit Löschprotokoll | SyRS-028 | StRS-013 |
| SwRS-017 | Attributgesteuerte Änderungsprotokollierung | SyRS-046 | StRS-014 |
| SwRS-018 | Datenmodell- und Namenskonventionen | SyRS-039 | StRS-004, StRS-019 |
| SwRS-019 | Rechteabhängige Preisrücksetzung | SyRS-017, SyRS-021 | StRS-002, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-020 | Datenmodell Provisionsermittlung | SyRS-013 | StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 |
| SwRS-021 | Getrennte Auswertungskomponenten | SyRS-013 | StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 |
| SwRS-022 | Lokalisierung je Assembly | SyRS-048 | StRS-018 |
| SwRS-023 | Drei Hostvarianten des Web-Service | SyRS-035, SyRS-040 | StRS-009, StRS-019, StRS-025 |
| SwRS-024 | Anbieterstruktur externe Artikelsuche | SyRS-034 | StRS-009, StRS-010, StRS-020, StRS-021 |
| SwRS-025 | Vererbungsstruktur der Authentifikatoren | SyRS-001, SyRS-002, SyRS-003, SyRS-006 | StRS-002, StRS-004, StRS-011, StRS-022 |
| SwRS-026 | **[HYPOTHESE]** Ablage/Prüfung Benutzerkennwörter | SyRS-003, SyRS-004 | StRS-002, StRS-022 |
| SwRS-027 | Portalkomponenten Dokumentensignatur | SyRS-010 | StRS-002, StRS-023 |
| SwRS-028 | Typisierter Einstellungszugriff | SyRS-049 | StRS-024 |
| SwRS-029 | Basisklasse aller Hintergrunddienste | SyRS-035, SyRS-045 | StRS-001, StRS-009, StRS-025 |
| SwRS-030 | Umschlagtypen Legacy-Schnittstelle | SyRS-010, SyRS-011, SyRS-031 | StRS-001, StRS-002, StRS-023 |
| SwRS-031 | Sitzungsfassade für Datenzugriff | SyRS-012, SyRS-017, SyRS-032, SyRS-033 | StRS-001, StRS-002, StRS-005, StRS-008, StRS-014, StRS-015, StRS-019 |
| SwRS-032 | Zeichenkettenverkettung in SQL (Nummernvergabe) | SyRS-018, SyRS-036 | StRS-003, StRS-005, StRS-014, StRS-019 |
| SwRS-033 | Skriptbasierte Schemafortschreibung | SyRS-039 | StRS-004, StRS-019 |
| SwRS-034 | Zweistufige Serverkonfiguration | SyRS-037, SyRS-040, SyRS-041, SyRS-049 | StRS-011, StRS-019, StRS-024 |
| SwRS-035 | Zentrale Build- und Versionierungsvorgaben | SyRS-042, SyRS-043, SyRS-044 | StRS-005, StRS-014, StRS-019 |
| SwRS-036 | MVVM-Struktur des Fachclients | SyRS-032, SyRS-048 | StRS-001, StRS-018, StRS-019 |
| SwRS-037 | **[HYPOTHESE]** Telemetrieerhebung | SyRS-035 | StRS-009, StRS-025 |
| SwRS-038 | Zwischenspeicherung Stammdaten | SyRS-012, SyRS-038 | StRS-002, StRS-011, StRS-019 |
| SwRS-039 | Umfang des persistenten Datenmodells | SyRS-039 | StRS-004, StRS-019 |
| SwRS-040 | Getrenntes Rechtemodell Portalkonten | SyRS-006, SyRS-026 | StRS-002, StRS-004, StRS-007, StRS-011 |
---
## 3. Abdeckungsübersicht
| Kennzahl | Wert |
|---|---|
| StRS-Anforderungen mit mindestens einem SyRS-Verweis | 25 von 25 (100 %) |
| SyRS-Anforderungen mit mindestens einem StRS-Verweis | 49 von 49 (100 %) |
| SyRS-Anforderungen mit mindestens einem SwRS-Verweis | 49 von 49 (100 %) |
| SwRS-Anforderungen mit mindestens einem SyRS-Verweis | 40 von 40 (100 %) |
| SwRS-Anforderungen mit direktem StRS-Verweis im eigenen Tracelinks-Feld | 40 von 40 (100 %) |
| Anforderungen ohne Artefaktbeleg | 0 |
| Anforderungen ohne `PRIMÄR`-Beleg | 0 |
| Tracelinks auf nicht existierende IDs | 0 |
| Mehrfach vergebene IDs | 0 |
| Als `[HYPOTHESE]` gekennzeichnet | 6 (SyRS-011, SyRS-041, SyRS-042, SwRS-010, SwRS-026, SwRS-037) |
| Mit Zusatz `Workaround` im Feld `Status` | 18 |
---
## 4. Hinweis zur Verweisrichtung
Die Verweise sind auf jeder Ebene vollständig: Jede Anforderung ist von beiden Nachbarebenen aus erreichbar. Sie sind jedoch nicht in jedem Einzelfall spiegelbildlich notiert – ein Verweis ist teils nur in der einen, teils nur in der anderen Anforderung geführt. Beide Matrizen oben lösen das auf, indem sie die Vereinigung aus Vorwärts- und Rückwärtsverweisen bilden. Für eine Folge-Iteration ist die vollständige Spiegelung aller Verweise in den Quelldokumenten vorgemerkt (siehe `Analysebericht.md`, Abschnitt „Nachschlag").
---
## 5. Konsolidierungskandidaten (Querschnitt)
Anforderungen, die im Feld `Konsolidierung` einen Kandidaten führen – also fachliche Redundanz markieren, die im Zielsystem zusammenzuführen ist:
| Thema | Beteiligte Anforderungen | Kernaussage |
|---|---|---|
| **Zwei REST-Schnittstellen** | SyRS-010, SyRS-031, SwRS-030 | 2 599 Legacy-Methoden neben 160 modernen Endpunkten; größter Einzelposten der Neuimplementierung |
| **Vierfache Belegpersistenz** | SwRS-007 | Legacy-Tabelle + moderne Sicht + temporäre Entität + Repository bilden dieselbe Struktur ab |
| **Zwei Einstellungsspeicher** | StRS-024, SyRS-049, SwRS-028 | `Stammdat` (728 Einträge) neben `ApplicationSettings` (492 Einträge) |
| **Zwei Identitäts-/Rechtemodelle** | SwRS-026, SwRS-040 | Mitarbeiter gruppenbasiert, Portalkonten direkt; zwei getrennte Kennwortprüfungen mit identischem Verfahren |
| **Autorisierung an drei Stellen** | SyRS-009 | Controller-Attribut, `Result`-Prüfung in `*WebServiceBL`, `HasUserRight` in `*BL` |
| **Einschränkende Rechte je Domäne** | StRS-003, SyRS-013 | „nur eigene" / „nur eigene Filiale" je Domäne eigenständig aufgelöst |
| **Belegartspezifische Rechtepaare** | SwRS-019 | Sieben Rechtepaare für Einkaufs-/Verkaufspreisänderung bilden dieselbe Regel ab |
| **Freigabe per Zweitanmeldung** | SyRS-021, SyRS-025 | Identisches Muster für Mindestpreis und negative Lagerbuchung |
| **46 Einzelprüfungen im Belegspeichern** | SyRS-017 | Als Regelkatalog je Belegart zusammenführbar |
| **EDI-Mapping je Distributor** | StRS-009 | Kopf-/Positions-Mapping siebenfach dupliziert |
| **Sieben Preisquellen** | StRS-020, SwRS-024 | Je eigene Abruf-, Auswertungs- und Anzeigelogik |
| **Drei Anonymisierungsroutinen** | StRS-013, SwRS-016 | Strukturgleiche Kontaktdaten, dreifach implementiert |
| **Sieben Ressourcenbestände** | SwRS-022 | Teilweise gleichlautende Texte |
| **Zwei Ticketzustandsmodelle** | SwRS-012 | Konfigurierbare Ticketzustände gegenüber fester `RequestStateEnum` |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 19 (Lauf M)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:55+02:00
- **Endzeit:** 2026-08-25T20:55:56+02:00
- **Dauer gesamt:** 00:56:01 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:55:60 (`duration_ms`) — API: 00:55:13
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-5070`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 247
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.191 Input-/19 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 162 |
| Output-Tokens | 268.834 (davon 21.146 Thinking-Tokens) |
| Cache-Write-Tokens | 578.094 |
| Cache-Read-Tokens | 24.008.783 |
| Agent-Turns | 177 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 162 | 4.191 | 4.353 |
| Output-Tokens | 268.834 | 19 | 268.853 |
| Cache-Write-Tokens | 578.094 | 0 | 578.094 |
| Cache-Read-Tokens | 24.008.783 | 0 | 24.008.783 |
| Tokens gesamt | 24.855.873 | 4.210 | **24.860.083** |
**Tokens gesamt: 24.860.083** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `cad89937-98ba-4a32-a943-eaa5ca8815c4`
- **Permission-Denials:** **1** – 1 x `PowerShell` - `New-Item -ItemType Directory` auf das eigene, bereits vorhandene `Ergebnisse\`-Verzeichnis; von `PowerShell(New-Item:*)` geblockt. Folgenlos, alle 7 Artefakte entstanden.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 70.251 B | 25 Anforderungen |
| `SyRS.md` | 118.533 B | 49 Anforderungen |
| `SwRS.md` | 101.763 B | 40 Anforderungen |
| `Traceability.md` | 16.627 B | 51 Datenzeilen |
| `Hypothesen.md` | 14.857 B | 17 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 21.899 B | Domänenbegriffe |
| `Analysebericht.md` | 26.614 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **114 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,9 % |
| SyRS | 49 | 43,0 % |
| SwRS | 40 | 35,1 % |
| **Gesamt** | **114** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 38 | 33,3 % |
| Sicherheit | 29 | 25,4 % |
| Daten | 19 | 16,7 % |
| Schnittstelle | 10 | 8,8 % |
| nicht-funktional | 4 | 3,5 % |
| nicht-funktional (Performance-Effizienz) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit, ISO/IEC 25010: Fehlertoleranz) | 1 | 0,9 % |
| nicht-funktional (Zuverlässigkeit – Fehlertoleranz, Wiederherstellbarkeit) | 1 | 0,9 % |
| nicht-funktional (Wartbarkeit – Analysierbarkeit) | 1 | 0,9 % |
| nicht-funktional (Sicherheit – Ressourcenschutz) | 1 | 0,9 % |
| (8 weitere) | 8 | 7,0 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 421 |
| davon `PRIMÄR` | 314 (74,6 %) |
| davon `SEKUNDÄR` | 35 (8,3 %) |
| davon `KONTEXT` | 72 (17,1 %) |
| Belege je Anforderung (Median) | 4,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 114 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 94,7 % |
| als `HYPOTHESE` gekennzeichnet | 6 | 5,3 % |
| als Workaround vermerkt | 18 | 15,8 % |
| Konsolidierungskandidaten | 23 | 20,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (50 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 114 von 114 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(247 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":3312937,"num_turns":177,"stop_reason":"end_turn","session_id":"cad89937-98ba-4a32-a943-eaa5ca8815c4","total_cost_usd":24.5112775,"usage":{"input_tokens":162,"cache_creation_input_tokens":578094,"cache_read_input_tokens":24008783,"output_tokens":268834,"output_tokens_details":{"thinking_tokens":21146},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":578094,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1182,"cache_read_input_tokens":598251,"cache_creation_input_tokens":779,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":779},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4191,"outputTokens":19,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004286,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":162,"outputTokens":268834,"cacheReadInputTokens":24008783,"cacheCreationInputTokens":578094,"webSearchRequests":0,"costUSD":24.5069915,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[{"tool_name":"PowerShell","tool_use_id":"toolu_01VHU1qpzzX7x2TL9ovp6x6Y","tool_input":{"command":"$out=\"c:\\DEV\\MasterArbeit\\Versuche\\Versuch_01\\01_Lauf_2026-08-25_195916_opus5_solo_v3.6.0-5070\\Ergebnisse\"; New-Item -ItemType Directory -Force -Path $out | Out-Null; Test-Path $out","description":"Create output directory"}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Alle sieben Ergebnisdateien liegen im vorgegebenen Ausgabeverzeichnis; die Codebasis ist unverändert (`git status` leer, HEAD `79c1142f48`).\n\n## Ergebnis\n\n**114 Anforderungen** (25 StRS, 49 SyRS, 40 SwRS) mit **421 Artefaktbelegen** (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`), 362 KB Spezifikation.\n\n**Konsistenzcheck (maschinell, dokumentiert in `Analysebericht.md` §4):**\n- keine doppelten IDs, keine Tracelinks auf nicht existierende IDs\n- 0 Anforderungen ohne Beleg, 0 ohne `PRIMÄR`-Beleg — die verschärfte Evidenzpflicht für Sicherheit/Abrechnung/Berechtigungen ist damit durchgängig erfüllt\n- Vor-/Rückwärts-Traceability auf allen drei Ebenen zu 100 % geschlossen\n- Sieben im Verlauf gefundene Tracelink-Fehler sind korrigiert und in §4.1 offengelegt\n\n**Drei Befunde am laufenden System**, unabhängig von der Neuimplementierung:\n1. **221 von 2 599 Legacy-REST-Methoden ohne `[Authenticate]`** — darunter schreibende Operationen (`DeleteLogo`, `SaveCustomerSpecialArticle`, `DeleteContractExternalArticleImportHead`). Als Hypothese H-01 markiert, weil ein impliziter Schutz durch die WCF-Bridge statisch nicht ausschließbar war.\n2. **Ungesalzenes SHA-1 für Mitarbeiter- und Portalkennwörter**, Kennwort als Teil der SQL-Abfrage. Ist-Zustand durch `PRIMÄR`-Belege eindeutig; im Code steht `// TODO the password should be salted!!!`.\n3. **`NU1901`–`NU1904` (bekannte Paketschwachstellen) sind bewusst von `TreatWarningsAsErrors` ausgenommen.**\n\n**Wo die Spezifikation schwach ist** (§5.4, offengelegt statt kaschiert): 22 Anforderungen haben mindestens so viele `SEKUNDÄR`/`KONTEXT`- wie `PRIMÄR`-Belege — systematisch dort, wo `docs/` eine fertige Architekturbeschreibung lieferte und deshalb die Codeverifikation zurückgestellt wurde. Am schwächsten belegt ist ausgerechnet **SwRS-007 (zweigleisige Belegpersistenz)**, die aufwendigste Struktur der Belegverarbeitung.\n\n**Nicht abgedeckt:** KI-Bereich, Produktion/PLM, Passwort-Manager, TAPI, MyDay/TaskManager/Kalender, SelfCare (137 KB). Von `ReceiptBL.cs` (609 KB) wurden ~9 % gelesen — 39 der 46 Belegprüfungen sind namentlich erfasst, aber inhaltlich offen. Das ist der Nachschlag mit dem höchsten erwarteten Ertrag (Rang 1 in §7).","ttft_ms":3358,"ttft_stream_ms":1188,"time_to_request_ms":37,"type":"result","duration_ms":3359594,"uuid":"c879d5f1-e3f1-4b1e-a910-6486bd2333c8","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,9 % |
| SyRS | 49 | 43,0 % |
| SwRS | 40 | 35,1 % |
| **Gesamt** | **114** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 38 | 33,3 % |
| Sicherheit | 29 | 25,4 % |
| Daten | 19 | 16,7 % |
| Schnittstelle | 10 | 8,8 % |
| nicht-funktional | 4 | 3,5 % |
| nicht-funktional (Performance-Effizienz) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit, ISO/IEC 25010: Fehlertoleranz) | 1 | 0,9 % |
| nicht-funktional (Zuverlässigkeit – Fehlertoleranz, Wiederherstellbarkeit) | 1 | 0,9 % |
| nicht-funktional (Wartbarkeit – Analysierbarkeit) | 1 | 0,9 % |
| nicht-funktional (Sicherheit – Ressourcenschutz) | 1 | 0,9 % |
| (8 weitere) | 8 | 7,0 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 421 |
| davon `PRIMÄR` | 314 (74,6 %) |
| davon `SEKUNDÄR` | 35 (8,3 %) |
| davon `KONTEXT` | 72 (17,1 %) |
| Belege je Anforderung (Median) | 4,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 114 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 94,7 % |
| als `HYPOTHESE` gekennzeichnet | 6 | 5,3 % |
| als Workaround vermerkt | 18 | 15,8 % |
| Konsolidierungskandidaten | 23 | 20,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (50 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 114 von 114 mit Tracelinks (100,0 %) |

Some files were not shown because too many files have changed in this diff Show More