Files
cannamanage/docs/sprint-9/cannamanage-sprint9-testplan.md
T
Patrick Plate 26a77dd269 feat(sprint9): Phase 1 — Data model + ReportGenerator infrastructure
- 7 new enums: ReportType, ExportFormat, DestructionMethod, TransportStatus,
  ComplianceArea, ComplianceStatus, RetentionCategory
- Extended: StaffPermission (+3), AuditEventType (+5), NotificationType (+2)
- Flyway V23-V29: destruction_records, transport_records, propagation_sources,
  prevention_activities, generated_reports, compliance_deadlines, distribution THC/CBD
- 6 new JPA entities extending AbstractTenantEntity
- 6 new Spring Data repositories with tenant-scoped queries
- ReportGenerator<T> interface + ReportGeneratorService (auto-discovery, format dispatch)
- ComplianceRecordsController (CRUD for destruction/transport/propagation/prevention)
- ComplianceDeadlineController (create, list, complete, overdue)
- DateRangeReportParameters record for report generation
2026-06-15 12:01:06 +02:00

29 KiB

Sprint 9 Test Plan — Berichtszentrale (Report Center)

Date: 2026-06-15 Author: Patrick Plate / Lumen (Architect) Status: Draft v2 (updated with panel review advisory items) Basis: cannamanage-sprint9-plan.md v2 Total Test Cases: 80


Test Overview

ID Description Type Class/Location Status
T-01 Destruction record CRUD Unit DestructionRecordServiceTest
T-02 Transport record CRUD Unit TransportRecordServiceTest
T-03 Propagation source CRUD Unit PropagationSourceServiceTest
T-04 Prevention activity CRUD Unit PreventionActivityServiceTest
T-05 Generated report record keeping Unit GeneratedReportServiceTest
T-06 Compliance deadline CRUD + status Unit ComplianceDeadlineServiceTest
T-07 EÜR calculation correctness Unit EurReportGeneratorTest
T-08 EÜR zero-income edge case Unit EurReportGeneratorTest
T-09 EÜR multi-category expense grouping Unit EurReportGeneratorTest
T-10 EÜR CSV encoding ISO-8859-1 Unit EurReportGeneratorTest
T-11 EÜR decimal comma format Unit EurReportGeneratorTest
T-12 Kassenbuch export with running balance Unit KassenbuchExportGeneratorTest
T-13 Kassenbuch period filtering Unit KassenbuchExportGeneratorTest
T-14 Fee confirmation per member Unit FeeConfirmationGeneratorTest
T-15 Fee confirmation batch generation Unit FeeConfirmationGeneratorTest
T-16 Annual authority report - all fields populated Unit AnnualAuthorityReportGeneratorTest
T-17 Annual authority report - by-strain breakdown Unit AnnualAuthorityReportGeneratorTest
T-18 Annual authority report - stock reconciliation check Unit AnnualAuthorityReportGeneratorTest
T-19 Annual authority report - empty year (no activity) Unit AnnualAuthorityReportGeneratorTest
T-20 Annual authority report - JSON schema validation Unit AnnualAuthorityReportGeneratorTest
T-21 Distribution log - date range filter Unit DistributionLogGeneratorTest
T-22 Distribution log - quota violation flagging Unit DistributionLogGeneratorTest
T-23 Distribution log - Heranwachsende THC limit flag Unit DistributionLogGeneratorTest
T-24 Distribution log - CSV semicolons + ISO-8859-1 Unit DistributionLogGeneratorTest
T-25 Stock inventory - point-in-time snapshot Unit StockInventoryReportGeneratorTest
T-26 Stock inventory - includes propagation material count Unit StockInventoryReportGeneratorTest
T-27 Destruction protocol - sequential numbering Unit DestructionProtocolGeneratorTest
T-28 Destruction protocol - witness fields Unit DestructionProtocolGeneratorTest
T-29 Destruction protocol - annual totals Unit DestructionProtocolGeneratorTest
T-30 Cultivation report - harvest aggregation by strain Unit CultivationReportGeneratorTest
T-31 Transport certificate - all §22(4) fields present Unit TransportCertificateGeneratorTest
T-32 Transport certificate - PDF single page Unit TransportCertificateGeneratorTest
T-33 Full authority export - ZIP structure valid Unit FullAuthorityExportGeneratorTest
T-34 Full authority export - JSON files parseable Unit FullAuthorityExportGeneratorTest
T-35 Full authority export - DSGVO minimization (birth year only) Unit FullAuthorityExportGeneratorTest
T-36 Full authority export - includes README.txt Unit FullAuthorityExportGeneratorTest
T-37 Distribution info sheet - all §21(2) fields Unit DistributionInfoSheetGeneratorTest
T-38 Distribution info sheet - health warnings present Unit DistributionInfoSheetGeneratorTest
T-39 VVT generator - pre-filled template complete Unit VvtGeneratorTest
T-40 VVT generator - club-specific data inserted Unit VvtGeneratorTest
T-41 TOM generator - all 7 control areas present Unit TomGeneratorTest
T-42 DSFA generator - structure correct Unit DsfaGeneratorTest
T-43 Deletion concept - all retention categories listed Unit DeletionConceptGeneratorTest
T-44 Member list registry - §67 BGB format Unit MemberListRegistryGeneratorTest
T-45 Member list registry - minimal data only Unit MemberListRegistryGeneratorTest
T-46 Board change notice - old vs new composition Unit BoardChangeNoticeGeneratorTest
T-47 Annual board report - combines all data sources Unit AnnualBoardReportGeneratorTest
T-48 Compliance status - GREEN when all obligations met Unit ComplianceDashboardServiceTest
T-49 Compliance status - YELLOW when deadline within 30 days Unit ComplianceDashboardServiceTest
T-50 Compliance status - RED when deadline passed Unit ComplianceDashboardServiceTest
T-51 Compliance status - KCanG area calculation Unit ComplianceDashboardServiceTest
T-52 Retention service - identifies expired records Unit RetentionServiceTest
T-53 Retention service - respects different retention periods Unit RetentionServiceTest
T-54 Retention service - never auto-deletes Unit RetentionServiceTest
T-55 Deadline scheduler - rolls annual deadlines Unit ComplianceDeadlineSchedulerTest
T-56 Deadline scheduler - creates notifications Unit ComplianceDeadlineSchedulerTest
T-57 PDF generation - German umlauts render correctly Integration PdfRenderingTest
T-58 PDF generation - legal reference in footer Integration PdfRenderingTest
T-59 PDF generation - club letterhead Integration PdfRenderingTest
T-60 Report controller - generate EÜR endpoint Integration ReportControllerTest
T-61 Report controller - authority annual report endpoint Integration ReportControllerTest
T-62 Report controller - full export ZIP endpoint Integration ReportControllerTest
T-63 Report controller - permission check (ADMIN only) Integration ReportControllerTest
T-64 Destruction controller - CRUD + PDF Integration DestructionRecordControllerTest
T-65 Transport controller - CRUD + certificate Integration TransportRecordControllerTest
T-66 Sidebar renders grouped navigation E2E navigation.spec.ts
T-67 Berichtszentrale page loads with compliance cards E2E reports.spec.ts
T-68 Report download flow (generate → download PDF) E2E reports.spec.ts
T-69 Rate limiter - 6th report in 1 min returns 429 Integration ReportControllerTest
T-70 Rate limiter - different tenant not affected Integration ReportControllerTest
T-71 CSV injection prevention - dangerous cell prefixes escaped Unit CsvExportUtilTest
T-72 CSV injection - formula in member name does not execute Unit CsvExportUtilTest
T-73 Authority export re-authentication required Integration ReportControllerTest
T-74 Authority export - expired reconfirm token rejected Integration ReportControllerTest
T-75 Authority export - reason field minimum length enforced Integration ReportControllerTest
T-76 Streaming ZIP - large export does not OOM Integration FullAuthorityExportGeneratorTest
T-77 Breach notification - Art. 33 section present Unit BreachNotificationGeneratorTest
T-78 Breach notification - Art. 34 section separate Unit BreachNotificationGeneratorTest
T-79 Breach notification - 72h deadline reminder included Unit BreachNotificationGeneratorTest
T-80 Empty-state Berichtszentrale shows onboarding for new club E2E reports.spec.ts

Status: Pending | Passed | Failed | ⏭️ Skipped


Test Cases — Detailed

T-01: Destruction Record CRUD

Type: Unit Class: DestructionRecordServiceTest Method: testCreateDestructionRecord(), testListByDateRange(), testDeleteNotAllowed()

Preconditions:

  • Tenant with active batch in stock

Scenarios:

# Input Expected Result
a Valid destruction (batch, 100g, INCINERATION, reason, witness) Record created, stock updated (decrease by 100g)
b Destruction with 0 grams Validation error: grams must be > 0
c Destruction exceeding batch remaining stock Validation error: cannot destroy more than available
d List destructions for date range Only records within range returned
e Delete destruction record Rejected: destruction records are immutable (audit trail)

T-07: EÜR Calculation Correctness

Type: Unit Class: EurReportGeneratorTest Method: testEurCalculation_normalYear()

Preconditions:

  • 12 months of financial transactions (income + expenses)
  • Multiple expense categories

Scenarios:

# Input Expected Result
a Year 2025 with €54000 income, €46000 expenses EÜR shows Überschuss €8000
b Opening balance €5000, closing balance €13000 Balance change matches Überschuss
c 6 expense categories All categories listed with correct subtotals
d Amounts in cents (internal) Display in Euro with comma decimals (1.234,56)

T-10: EÜR CSV Encoding ISO-8859-1

Type: Unit Class: EurReportGeneratorTest Method: testCsvEncoding()

Scenarios:

# Input Expected Result
a Category "Büroausstattung" with umlaut CSV file readable in ISO-8859-1, ü correctly encoded
b Amount 1234.56 CSV shows "1234,56" (decimal comma)
c Field separator Semicolons (;) not commas
d Line ending CRLF (Windows-compatible for DATEV)

T-16: Annual Authority Report — All Fields Populated

Type: Unit Class: AnnualAuthorityReportGeneratorTest Method: testAnnualReport_complete()

Preconditions:

  • Grow module has harvest records for 3 strains
  • Distribution records for 2025
  • 2 destruction records
  • Stock snapshot available for Dec 31

Scenarios:

# Input Expected Result
a Year 2025 Report contains all 4 sections: cultivated, distributed, destroyed, end-stock
b 3 strains with different THC/CBD Each strain listed separately with correct averages
c Cross-check: cultivated - distributed - destroyed = stock change Discrepancy < 1g (rounding) or flagged
d JSON output Valid JSON matching defined schema
e PDF output Contains legal reference "§26 Abs. 3 KCanG" in footer

T-22: Distribution Log — Quota Violation Flagging

Type: Unit Class: DistributionLogGeneratorTest Method: testQuotaViolationFlags()

Preconditions:

  • Member A (age 25): received 26g on one day (exceeds 25g/day limit)
  • Member B (age 19): received cannabis with 12% THC (exceeds 10% for Heranwachsende)
  • Member C (age 30): received 52g in one month (exceeds 50g/month)

Scenarios:

# Input Expected Result
a Member A daily violation Report flags: "TAGESLIMIT ÜBERSCHRITTEN: 26g > 25g"
b Member B THC violation Report flags: "THC-LIMIT HERANWACHSENDE: 12% > 10%"
c Member C monthly violation Report flags: "MONATSLIMIT ÜBERSCHRITTEN: 52g > 50g"
d Member D (age 25, 20g/day, 45g/month) No flags — within all limits

T-33: Full Authority Export — ZIP Structure Valid

Type: Unit Class: FullAuthorityExportGeneratorTest Method: testZipStructure()

Scenarios:

# Input Expected Result
a Generate full export ZIP contains: README.txt, distributions.json, distributions.csv, stock.json, destructions.json, cultivation.json, transports.json, members.json, summary.pdf
b Each JSON file Valid JSON, parseable without errors
c members.json Contains ONLY: name, firstName, birthYear — NO address, NO full DOB, NO phone
d README.txt Contains: generation date, legal basis reference, file descriptions

T-35: Full Authority Export — DSGVO Minimization

Type: Unit Class: FullAuthorityExportGeneratorTest Method: testDsgvoMinimization()

Critical test — ensures we don't leak unnecessary personal data to authorities.

Scenarios:

# Input Expected Result
a Member with full profile (name, address, phone, email, DOB 1990-05-15) Export contains only: "Max", "Müller", 1990
b Distribution record Contains member name + birth year, NOT member ID or address
c No bank details in any export file Grep for IBAN patterns returns zero matches
d No email addresses in export Grep for @ returns zero matches

T-48: Compliance Status — GREEN When All Obligations Met

Type: Unit Class: ComplianceDashboardServiceTest Method: testGreenStatus()

Preconditions:

  • Annual authority report generated for previous year
  • EÜR generated for previous year
  • VVT exists and updated within last 12 months
  • Next MV scheduled
  • All board terms valid

Scenarios:

# Input Expected Result
a All conditions met Overall status: GREEN
b KCanG area GREEN: annual report submitted, records complete
c Finance area GREEN: EÜR generated, no overdue deadlines
d DSGVO area GREEN: VVT exists and recent
e Verein area GREEN: MV scheduled, board terms valid

T-50: Compliance Status — RED When Deadline Passed

Type: Unit Class: ComplianceDashboardServiceTest Method: testRedStatus()

Preconditions:

  • Current date: February 15
  • Annual authority report for previous year NOT generated (deadline was Jan 31)

Scenarios:

# Input Expected Result
a Authority report overdue KCanG status: RED
b Overall status RED (worst of all areas)
c Deadline record Status marked OVERDUE

T-52: Retention Service — Identifies Expired Records

Type: Unit Class: RetentionServiceTest Method: testIdentifiesExpiredRecords()

Preconditions:

  • Distribution record created 6 years ago (past 5-year KCanG retention)
  • Financial transaction created 11 years ago (past 10-year AO retention)
  • MV protocol from 20 years ago (indefinite retention — should NOT be flagged)

Scenarios:

# Input Expected Result
a 6-year-old distribution record Flagged for deletion review
b 11-year-old financial transaction Flagged for deletion review
c 20-year-old MV protocol NOT flagged (indefinite retention)
d 4-year-old distribution record NOT flagged (within 5-year period)

T-54: Retention Service — Never Auto-Deletes

Type: Unit Class: RetentionServiceTest Method: testNeverAutoDeletes()

Critical safety test.

Scenarios:

# Input Expected Result
a Run retention check with expired records No records deleted from database
b Expired record Status changed to "RETENTION_EXPIRED", admin notification created
c Admin confirms deletion THEN record is soft-deleted (retention log entry created)
d Without admin confirmation Record persists indefinitely

T-57: PDF Generation — German Umlauts Render Correctly

Type: Integration Class: PdfRenderingTest Method: testGermanCharacters()

Scenarios:

# Input Expected Result
a Text with äöüÄÖÜß All characters render correctly in PDF
b Club name "Grüner Daumen e.V." Renders correctly in letterhead
c Category "Büroausstattung" Renders correctly in EÜR table
d Legal text "§26 Abs. 3 KCanG" § symbol renders correctly
e Euro amounts "1.234,56 €" Euro sign renders correctly

T-63: Report Controller — Permission Check

Type: Integration Class: ReportControllerTest Method: testPermissions()

Scenarios:

# Input Expected Result
a ADMIN requests EÜR 200 OK + PDF
b STAFF (Kassenwart) requests EÜR 200 OK + PDF (finance permission)
c MEMBER requests EÜR 403 Forbidden
d ADMIN requests authority export 200 OK + ZIP
e STAFF without finance permission requests EÜR 403 Forbidden
f Unauthenticated request 401 Unauthorized

T-66: Sidebar Renders Grouped Navigation

Type: E2E (Playwright) File: cannamanage-frontend/e2e/authenticated/navigation.spec.ts

Scenarios:

# Action Expected Result
a Load dashboard page Sidebar shows 4 groups: Betrieb, Kommunikation, Verwaltung, Compliance
b Click group header "Kommunikation" Group collapses/expands
c Navigate to /reports "Berichtszentrale" item highlighted in Compliance group
d All existing URLs still work /members, /distributions, /stock, /grow, /finance, /assemblies all accessible

T-67: Berichtszentrale Page Loads

Type: E2E (Playwright) File: cannamanage-frontend/e2e/authenticated/reports.spec.ts

Scenarios:

# Action Expected Result
a Navigate to /reports Page loads with compliance status cards
b Compliance cards visible 4 cards: KCanG, Finanzen, DSGVO, Verein — each with status color
c Report categories visible 4 category sections with report listings
d Click "EÜR generieren" Year picker appears, generate button enabled
e Click "Behörden-Export" Confirmation dialog shown (due to data sensitivity)

T-68: Report Download Flow

Type: E2E (Playwright) File: cannamanage-frontend/e2e/authenticated/reports.spec.ts

Scenarios:

# Action Expected Result
a Select year 2025, click generate EÜR PDF Download triggered, file non-empty
b Generate distribution log for last month Download triggered, PDF contains data
c Report appears in history table History shows: type, date, generated by
d Re-download from history Same file downloadable again

T-69: Rate Limiter - 6th Report in 1 Minute Returns 429

Type: Integration Class: ReportControllerTest Method: testRateLimit_sixthRequestReturns429()

Preconditions:

  • Authenticated admin user
  • Resilience4j rate limiter configured: 5 permits/minute/tenant

Scenarios:

# Action Expected Result
a Generate 5 reports in rapid succession All return 200 OK
b Generate 6th report within same minute Returns 429 Too Many Requests
c Response body contains "Rate limit exceeded" message Helpful German error message
d Response includes Retry-After header Header present with seconds value

T-70: Rate Limiter - Different Tenant Not Affected

Type: Integration Class: ReportControllerTest Method: testRateLimit_differentTenantNotBlocked()

Preconditions:

  • Two tenants configured in test

Scenarios:

# Action Expected Result
a Tenant A generates 5 reports (hitting limit) All return 200
b Tenant B generates 1 report immediately after Returns 200 OK (not affected by A's limit)

T-71: CSV Injection Prevention - Dangerous Cell Prefixes Escaped

Type: Unit Class: CsvExportUtilTest Method: testCsvInjection_dangerousPrefixesEscaped()

Preconditions:

  • CSV export utility available

Scenarios:

# Input Cell Value Expected Output
a =SUM(A1:A10) '=SUM(A1:A10)
b +cmd|'/C calc'|''!A0 '+cmd|'/C calc'|''!A0
c -2+3+cmd|'/C calc'|'!A0 '-2+3+cmd|'/C calc'|'!A0
d @SUM(A1:A10) '@SUM(A1:A10)
e Normal text value Normal text value (unchanged)
f 123.45 123.45 (numbers unchanged)

T-72: CSV Injection - Formula in Member Name Does Not Execute

Type: Unit Class: CsvExportUtilTest Method: testCsvInjection_memberNameWithFormula()

Preconditions:

  • Member with name =HYPERLINK("http://evil.com","Click") in database

Scenarios:

# Action Expected Result
a Export distribution log as CSV with this member Cell contains '=HYPERLINK(...) with leading quote
b Open CSV in LibreOffice Calc No formula execution, displays as text

T-73: Authority Export Re-Authentication Required

Type: Integration Class: ReportControllerTest Method: testAuthorityExport_requiresReauthentication()

Preconditions:

  • Authenticated admin user with valid session

Scenarios:

# Action Expected Result
a Call GET /api/reports/authority-export/zip without reconfirm token Returns 403 Forbidden
b Call POST /api/auth/reconfirm with correct password Returns fresh token (valid 30s)
c Call authority export with valid reconfirm token within 30s Returns 200 with ZIP stream
d Audit log entry created Records: who, when, reason, IP address

T-74: Authority Export - Expired Reconfirm Token Rejected

Type: Integration Class: ReportControllerTest Method: testAuthorityExport_expiredTokenRejected()

Preconditions:

  • Reconfirm token obtained but 31+ seconds elapsed

Scenarios:

# Action Expected Result
a Call authority export with 31-second-old reconfirm token Returns 403 Forbidden
b Error message indicates re-authentication required "Bestätigung abgelaufen. Bitte erneut authentifizieren."

T-75: Authority Export - Reason Field Minimum Length Enforced

Type: Integration Class: ReportControllerTest Method: testAuthorityExport_reasonFieldValidation()

Preconditions:

  • Valid reconfirm token

Scenarios:

# Reason Value Expected Result
a "" (empty) 400 Bad Request — reason required
b "test" (4 chars) 400 Bad Request — minimum 10 characters
c "." (1 char) 400 Bad Request — minimum 10 characters
d "Behördenanfrage vom 15.06.2026" (30 chars) 200 OK — accepted
e "Jährliche Prüfung der Dokumentation" 200 OK — accepted

T-76: Streaming ZIP - Large Export Does Not OOM

Type: Integration Class: FullAuthorityExportGeneratorTest Method: testStreamingZip_largeDataDoesNotOOM()

Preconditions:

  • Test data with 500 members, 5000 distributions, 200 destruction records
  • JVM heap limited to 256MB in test configuration

Scenarios:

# Action Expected Result
a Generate full authority export with large dataset Completes without OutOfMemoryError
b Response is streamed (chunked transfer encoding) Transfer-Encoding: chunked header present
c ZIP file is valid and contains all expected entries All 8 files present in ZIP
d Peak memory usage stays below heap limit No GC pressure spikes above 200MB

T-77: Breach Notification - Art. 33 Section Present

Type: Unit Class: BreachNotificationGeneratorTest Method: testBreachNotification_article33SectionComplete()

Preconditions:

  • Club with configured DPO and Landesdatenschutzbehörde contact

Scenarios:

# Check Expected Content
a Nature of breach field Present and editable placeholder
b Categories of data subjects Pre-filled: "Mitglieder der Anbauvereinigung"
c Approximate number affected Editable field with club member count pre-filled
d DPO contact details Auto-filled from club settings
e Likely consequences Pre-filled with Art. 9 health data risk template
f Measures taken/proposed Editable placeholder
g 72-hour deadline reminder Bold text: "Meldung innerhalb 72 Stunden nach Kenntnisnahme"

T-78: Breach Notification - Art. 34 Section Separate

Type: Unit Class: BreachNotificationGeneratorTest Method: testBreachNotification_article34SectionSeparate()

Preconditions:

  • Same as T-77

Scenarios:

# Check Expected Result
a Art. 34 section has separate heading "Benachrichtigung der Betroffenen (Art. 34 DSGVO)"
b Plain language requirement noted "In klarer und einfacher Sprache" instruction present
c Template is distinct from Art. 33 section Not merged — separate page/section in PDF
d Includes contact details for data subjects Phone, email, postal address fields

T-79: Breach Notification - 72h Deadline Reminder Included

Type: Unit Class: BreachNotificationGeneratorTest Method: testBreachNotification_72hDeadlineReminder()

Preconditions:

  • Generated breach notification PDF

Scenarios:

# Check Expected Content
a Deadline prominently displayed "72 Stunden" appears in bold or highlighted
b Authority contact for notification Landesdatenschutzbehörde name + URL/email
c "Zeitpunkt der Kenntnisnahme" field Date/time field for when breach was discovered
d Countdown note "Frist beginnt ab Kenntnisnahme, nicht ab Entdeckung"

T-80: Empty-State Berichtszentrale Shows Onboarding for New Club

Type: E2E (Playwright) File: cannamanage-frontend/e2e/authenticated/reports.spec.ts

Preconditions:

  • New tenant with zero generated reports

Scenarios:

# Action Expected Result
a Navigate to /reports as new club admin "Erste Schritte" banner visible
b Compliance cards show neutral state Gray "Einrichtung erforderlich" — NOT red indicators
c 4-step guide links present VVT, Jahresbericht, Kassenbuch, Fristen links all working
d Click "Verstanden, Dashboard anzeigen" Banner dismissed, normal view shown
e Generate one report in any category After refresh, traffic-light indicators appear
f Banner does not reappear after dismissal LocalStorage persists dismissal

Test Data Requirements

Seed Data Enhancements

For test scenarios to work, seed data must include:

Data Quantity Details
Financial transactions 50+ Spanning 12 months, multiple categories
Distributions with THC% 30+ Various strains, some near-limit quantities
Destruction records 3 Different methods, dates, witnesses
Transport records 2 With authority notification timestamps
Propagation sources 2 One person, one Anbauvereinigung
Prevention activities 5 Different activity types
Grow harvests with THC/CBD 5 Different strains, quantities
Stock entries 10+ Current stock by strain
Compliance deadlines 4 One per area, various due dates
Members aged 18-21 2 For Heranwachsende limit testing

Test Coverage Summary

Component Unit Tests Integration Tests E2E Tests Total
Phase 1 (CRUD) 6 2 0 8
Phase 2 (Financial) 9 1 0 10
Phase 3 (KCanG) 23 3 0 26
Phase 4 (DSGVO/Verein) 12 0 0 12
Phase 5 (Frontend) 0 0 4 4
Phase 6 (Compliance + Security) 9 8 0 17
Cross-cutting (CSV util) 2 0 0 2
Breach notification (v2) 3 0 0 3
Total 64 14 4 80 (was 68)

Critical Test Priorities

Tests marked as CRITICAL — must pass before sprint completion:

ID Test Why Critical
T-16 Annual authority report complete Legal obligation — §26(3) KCanG
T-22 Quota violation flagging Safety — prevents illegal distribution
T-33 Authority export ZIP structure Authority inspection readiness
T-35 DSGVO minimization in exports Privacy violation risk
T-54 Retention service never auto-deletes Data loss prevention
T-57 German umlauts in PDFs Usability — broken characters = unprofessional
T-63 Permission checks Security — unauthorized report access
T-69 Rate limiter enforced Security — prevents DoS via report generation
T-71 CSV injection prevention Security — prevents formula injection in exports
T-73 Authority export re-authentication Security — protects Art. 9 DSGVO health data
T-76 Streaming ZIP no OOM Reliability — prevents server crash on large exports
T-77 Breach notification Art. 33 complete Compliance — 72h notification obligation

Test Naming Convention

  • Test class: <OriginalClass>Test.java
  • Test method: test<What>_<Scenario>() or descriptive name
  • Location: mirrors source structure under src/test/java/
  • Assertions: use AssertJ for fluent assertions
  • Mocking: Mockito for service dependencies
  • PDF verification: extract text from generated PDF bytes using Apache PDFBox in test scope