# SDK Workflow — Sequenznummern & Navigation

Vollständige Referenz für das SDK-Workflow-System: Sequenznummern, Pakete, bedingte Sichtbarkeit und Navigationsfunktionen.

**Quelle:** `admin-compliance/lib/sdk/types.ts`

---

## Konzept

Jeder SDK-Schritt (Step) hat eine **globale Sequenznummer** (`seq`), die seine Position im gesamten Workflow eindeutig bestimmt — unabhängig vom Paket.

### Warum seq statt order?

Das alte `order`-Feld war paket-lokal (1, 2, 3 innerhalb eines Pakets). Das führte zu Problemen:

- Paket-zu-Paket-Navigation war hardcoded (Phasen 1→2)
- Neue Steps konnten nicht einfach zwischen bestehende Steps eingefügt werden
- Bedingte Sichtbarkeit (DSFA nur bei L2+) war nicht systematisch

Das `seq`-System löst alle drei Probleme:

- Navigation basiert auf globalem `seq`-Sort → kein hardcoded Phasenwechsel
- 100er-Lücken zwischen Steps erlauben späteres Einfügen ohne Umnummerierung
- `visibleWhen`-Funktion pro Step steuert Sichtbarkeit state-abhängig

---

## Lücken-Konvention

```
100er-Lücken:  innerhalb eines Pakets (Platz für 9 neue Steps zwischen je zwei)
300er-Lücken:  an Paket-Grenzen (700→1000, 1600→2000, 2400→3000, 3400→4000)
```

Beispiel — neuer Step zwischen `requirements` (1000) und `controls` (1100):
→ `seq: 1050` vergeben, `order` entsprechend setzen.

**Ausnahme `email-templates` (seq 4350):** Nachträglich zwischen `consent-management` (4300) und `notfallplan` (4400) eingefügt — nutzt die Hälfte der Lücke.

---

## Vollständige Step-Tabelle

### Paket 1 — Vorbereitung

| seq | id | Name | visibleWhen | isOptional |
|-----|----|------|-------------|-----------|
| 100 | `company-profile` | Unternehmensprofil | immer | nein |
| 200 | `compliance-scope` | Compliance Scope | immer | nein |
| 300 | `use-case-assessment` | Anwendungsfall-Erfassung | immer | nein |
| 400 | `import` | Dokument-Import | `customerType === 'existing'` | **ja** |
| 500 | `screening` | System Screening | immer | nein |
| 600 | `modules` | Compliance Modules | immer | nein |
| 700 | `source-policy` | Source Policy | immer | nein |

### Paket 2 — Analyse

| seq | id | Name | visibleWhen | isOptional |
|-----|----|------|-------------|-----------|
| 1000 | `requirements` | Requirements | immer | nein |
| 1100 | `controls` | Controls | immer | nein |
| 1200 | `evidence` | Evidence | immer | nein |
| 1300 | `risks` | Risk Matrix | immer | nein |
| 1400 | `ai-act` | AI Act Klassifizierung | immer | nein |
| 1500 | `audit-checklist` | Audit Checklist | immer | nein |
| 1600 | `audit-report` | Audit Report | immer | nein |

### Paket 3 — Dokumentation

| seq | id | Name | visibleWhen | isOptional |
|-----|----|------|-------------|-----------|
| 2000 | `obligations` | Pflichtübersicht | immer | nein |
| 2100 | `dsfa` | DSFA | Scope L2/L3/L4 oder `dsfaRequired`-Trigger | **ja** |
| 2200 | `tom` | TOMs | immer | nein |
| 2300 | `loeschfristen` | Löschfristen | immer | nein |
| 2400 | `vvt` | VVT | immer | nein |

### Paket 4 — Rechtliche Texte

| seq | id | Name | visibleWhen | isOptional |
|-----|----|------|-------------|-----------|
| 3000 | `einwilligungen` | Einwilligungen | immer | nein |
| 3100 | `consent` | Rechtliche Vorlagen | immer | nein |
| 3200 | `cookie-banner` | Cookie Banner | immer | nein |
| 3300 | `document-generator` | Dokumentengenerator | immer (→ `true`) | **ja** |
| 3400 | `workflow` | Document Workflow | immer | nein |

### Paket 5 — Betrieb

| seq | id | Name | visibleWhen | isOptional |
|-----|----|------|-------------|-----------|
| 4000 | `dsr` | DSR Portal | immer | nein |
| 4100 | `escalations` | Escalations | immer | nein |
| 4200 | `vendor-compliance` | Vendor Compliance | immer | nein |
| 4300 | `consent-management` | Consent Verwaltung | immer | nein |
| 4350 | `email-templates` | E-Mail-Templates | immer | nein |
| 4400 | `notfallplan` | Notfallplan & Breach Response | immer | nein |
| 4500 | `incidents` | Incident Management | immer | nein |
| 4600 | `whistleblower` | Hinweisgebersystem | immer | nein |
| 4700 | `academy` | Compliance Academy | immer | nein |
| 4800 | `training` | Training Engine | immer | nein |

---

## Bedingte Sichtbarkeit (`visibleWhen`)

Drei Steps haben eine `visibleWhen`-Funktion, die den `SDKState` auswertet:

### `import` (seq 400)

```typescript
visibleWhen: (state) => state.customerType === 'existing'
```

Nur sichtbar für **Bestandskunden**. Neukunden überspringen den Import-Schritt.

### `dsfa` (seq 2100)

```typescript
visibleWhen: (state) => {
  const level = state.complianceScope?.decision?.determinedLevel
  if (level && ['L2', 'L3', 'L4'].includes(level)) return true
  const triggers = state.complianceScope?.decision?.triggeredHardTriggers || []
  return triggers.some(t => t.rule.dsfaRequired)
}
```

Sichtbar wenn:
- Compliance-Scope-Level **L2, L3 oder L4** ermittelt wurde, **oder**
- Ein Hard-Trigger mit `dsfaRequired: true` ausgelöst wurde (z.B. Gesundheitsdaten, Minderjährige, Hochrisiko-KI)

Bei **L1-Kunden ohne DSFA-Trigger** ist der Schritt unsichtbar — TOM folgt direkt nach `obligations`.

### `document-generator` (seq 3300)

```typescript
visibleWhen: () => true
```

Immer sichtbar, aber `isOptional: true` — kann übersprungen werden.

---

## Prerequisite-Kette

Steps sind sequenziell verknüpft. Wichtige Besonderheiten:

| Step | prerequisiteSteps | Hinweis |
|------|-------------------|---------|
| `dsfa` | `['obligations']` | Nicht von `audit-report` abhängig |
| `tom` | `['obligations']` | Nicht von `dsfa` abhängig (da optional) |
| `workflow` | `['cookie-banner']` | Nicht von `document-generator` abhängig (da optional) |

**Regel:** Optionale Steps (`isOptional: true`) dürfen **keine** Pflicht-Steps als Voraussetzung haben.

---

## Navigationsfunktionen

Alle Funktionen in `admin-compliance/lib/sdk/types.ts`:

```typescript
// Alle Steps global nach seq sortiert (privat)
function getAllStepsSorted(): SDKStep[]

// Sichtbare Steps für aktuellen State
export function getVisibleSteps(state: SDKState): SDKStep[]

// Nächster/vorheriger sichtbarer Step
export function getNextVisibleStep(currentStepId: string, state: SDKState): SDKStep | undefined
export function getPreviousVisibleStep(currentStepId: string, state: SDKState): SDKStep | undefined

// Rückwärtskompatible Wrapper (state optional)
export function getNextStep(currentStepId: string, state?: SDKState): SDKStep | undefined
export function getPreviousStep(currentStepId: string, state?: SDKState): SDKStep | undefined

// Package/Phase gefiltert, seq-sortiert
export function getStepsForPackage(packageId: SDKPackageId): SDKStep[]
export function getStepsForPhase(phase: SDKPhase): SDKStep[]
```

### Verhalten ohne `state`

Wird kein State übergeben (Fallback), navigiert `getNextStep`/`getPreviousStep` seq-sortiert **ohne** `visibleWhen`-Filter. Das ist für Initialisierung und Tests nützlich.

### Context-Integration

`admin-compliance/lib/sdk/context.tsx` übergibt den State automatisch:

```typescript
const goToNextStep = useCallback(() => {
  const nextStep = getNextStep(state.currentStep, state)  // state mitgeben!
  if (nextStep) goToStep(nextStep.id)
}, [state, goToStep])

const canGoNext = useMemo(() => {
  return getNextStep(state.currentStep, state) !== undefined
}, [state])
```

---

## Neuen Step einfügen

1. **seq wählen:** Freien Wert in der gewünschten Lücke wählen (z.B. 1050 zwischen 1000 und 1100)
2. **Step-Eintrag anlegen** in `SDK_STEPS` (types.ts):

```typescript
{
  id: 'my-new-step',
  seq: 1050,
  phase: 1,
  package: 'analyse',
  order: 2,            // Lokale Ordnung innerhalb des Pakets
  name: 'Neuer Step',
  nameShort: 'Neu',
  description: 'Beschreibung',
  url: '/sdk/my-new-step',
  checkpointId: 'CP-NEW',
  prerequisiteSteps: ['requirements'],
  isOptional: false,
  // optional:
  visibleWhen: (state) => state.someFlag === true,
}
```

3. **Frontend-Seite** anlegen: `admin-compliance/app/sdk/my-new-step/page.tsx`
4. **Docs** erstellen: `docs-src/services/sdk-modules/my-new-step.md`
5. **mkdocs.yml** nav-Eintrag hinzufügen

---

## Deprecated

```typescript
/** @deprecated Use getVisibleSteps(state) instead */
export function getVisibleStepsForCustomerType(customerType: CustomerType): SDKStep[]
```

Diese Funktion filtert nur den `import`-Step nach Kundentyp — nicht state-aware. Bitte `getVisibleSteps(state)` verwenden.
