Files
cannamanage/docs/sprint-13/cannamanage-sprint13-analysis.md
2026-06-18 16:08:05 +02:00

7.2 KiB

Analysis: Sprint 13 — Production Hardening

Date: 2026-06-18 Author: Patrick Plate / Lumen (Planner) Status: v1 Sprint Theme: Production Hardening & Housekeeping


1. Problem Analysis

CannaManage has completed 12 sprints of feature development and is functionally complete for MVP. However, a comprehensive security review (2026-06-15) identified 4 production-blocking vulnerabilities that prevent deployment. Additionally, backend test coverage sits at ~12% (20 tests for 29K LOC), the CI/CD pipeline deploys without running tests, and various repo hygiene issues remain unaddressed.

Sprint 13 is a hardening sprint — no new features, purely focused on making the existing codebase production-ready.

Source Documents


2. Affected Components

Component Path Issue
DocumentController cannamanage-api/src/main/java/de/cannamanage/api/controller/DocumentController.java IDOR — no tenant check on download/delete
DocumentService cannamanage-service/src/main/java/de/cannamanage/service/DocumentService.java Path traversal via unsanitized filename
SecurityConfig cannamanage-api/src/main/java/de/cannamanage/api/security/SecurityConfig.java Missing /api/v1/documents/** matchers, CORS hardcoded
deploy.yml .gitea/workflows/deploy.yml Deploys without running tests
package.json cannamanage-frontend/package.json Wrong project name ("shadboard-nextjs-starter-kit")
cannamanage-domain cannamanage-domain/src/ 0 unit tests
cannamanage-service cannamanage-service/src/ Low test coverage on service layer

3. Current State (Ist-Zustand)

Security Posture

The security review gave a CONDITIONAL PASS — architecture is solid (multi-tenant via AbstractTenantEntity, BCrypt+SHA-256, RFC 9457 errors, GoBD append-only audit) but 4 specific issues block go-live:

# Blocker Severity Status Since
1 IDOR in DocumentController (download by raw UUID, no tenant verify) HIGH Sprint 9 (unfixed)
2 Path traversal in DocumentService (file.getOriginalFilename() unsanitized) HIGH Sprint 9 (unfixed)
3 JWT dev-secret fallback HIGH FIXEDapplication.properties now uses fail-on-startup marker
4 /api/v1/documents/** missing from SecurityConfig matchers HIGH Sprint 9 (unfixed)

Note: Blocker #3 is already resolved. The current application.properties:13 reads:

cannamanage.security.jwt.secret=${CANNAMANAGE_SECURITY_JWT_SECRET:CHANGE_ME_IN_PRODUCTION_THIS_WILL_FAIL_ON_STARTUP}

The JwtService.validateSecret() detects this marker and refuses startup. This leaves 3 active blockers.

CI/CD Pipeline

The current .gitea/workflows/deploy.yml triggers on push to main and:

  1. Checks out the commit
  2. Builds Docker images
  3. Deploys with docker compose up -d
  4. Checks backend health (actuator)
  5. ⚠️ Frontend check is non-blocking (doesn't fail the job)
  6. No tests run at all — neither backend (Maven) nor frontend (Vitest/Playwright)

Test Coverage

  • Backend: ~20 tests across cannamanage-api (GlobalExceptionHandlerTest, some controller tests). cannamanage-domain and cannamanage-service have minimal or zero coverage.
  • Frontend: Playwright integration specs (70+ tests) exist but are never run in CI. No Vitest unit tests in CI either.
  • Sprint 12 delivered the Docker Compose test infrastructure (docker-compose.test.yml) — it's ready to be wired into CI.

Repo Hygiene

Issue Location Impact
Wrong project name cannamanage-frontend/package.json"name": "shadboard-nextjs-starter-kit" Confusing, unprofessional
Dead .github/ folder .github/modernize/ GitHub-specific, project uses Gitea
No root README . No project documentation for new contributors
Leftover screenshot scripts cannamanage-frontend/*.mjs Dev clutter (gitignored PNGs, but scripts committed)
SonarQube findings 7 MAJOR/MINOR issues Dead fields, generic exceptions, string duplication

4. Risk Assessment

Risk Probability Impact Mitigation
Document data leak via IDOR High (any authenticated user) Critical (DSGVO breach, multi-tenant violation) Fix #1: Add tenant verification to DocumentController
Arbitrary file write via path traversal Medium (requires auth + upload permission) High (server compromise) Fix #2: Sanitize with FilenameUtils.getName()
Broken deployment from untested code Medium (no test gate) High (production outage) Add test step to deploy.yml
Low test confidence for future changes Ongoing Medium (regression risk) Expand backend test suite

5. Solution Options

Option A: Minimal Security Fix Only (2-3 hours)

  • Fix 3 remaining security blockers
  • No CI/CD changes, no test expansion, no cleanup
  • Pro: Fastest path to unblock deployment
  • Con: Leaves test debt and CI risk intact; next feature sprint can introduce regressions

Option B: Security + CI Quality Gate (4-6 hours)

  • Fix 3 security blockers
  • Add Maven test + Playwright test steps to CI
  • Basic repo cleanup (package.json, README)
  • Pro: Production-safe deployment pipeline, reasonable effort
  • Con: Test coverage still low for service/domain layer
  • Fix 3 security blockers
  • Expand backend test suite (target: DocumentService, AuthService, key service methods)
  • Wire tests into CI/CD pipeline (fail-fast on test failure)
  • CORS configuration externalization
  • Login rate limiting
  • Complete repo cleanup (README, package.json, dead files, SonarQube fixes)
  • Pro: Production-ready with confidence, clean repo, future-proof
  • Con: Full sprint investment (no new features)

6. Recommendation

Option C — This is the right time for a full hardening sprint. The project is feature-complete for MVP, Sprint 12 already built the test infrastructure, and the security blockers have been unfixed since Sprint 9. A half-measure (Option A/B) would leave known technical debt that compounds with every future sprint.

Priority ordering:

  1. Security fixes (unblocks production) — ~2 hours
  2. CI test gate (prevents future regressions) — ~2 hours
  3. Backend test expansion (confidence for the security fixes themselves) — ~4 hours
  4. Repo cleanup + CORS + rate limiting (polish) — ~2 hours

7. Open Questions

  • Should CORS allowed origins come from application.properties or environment variables?
  • Login rate limiting: Bucket4j (Spring-native) or custom filter with in-memory counter?
  • Target test coverage % for this sprint? (Suggest: cover all security-critical paths = DocumentService, AuthService, TenantFilterAspect)