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

140 lines
7.2 KiB
Markdown

# 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
- [`docs/security-code-review-final.md`](docs/security-code-review-final.md) — Full security review with 4 BLOCKERs
- [`docs/sprint-12/SPRINT-12-SUMMARY.md`](docs/sprint-12/SPRINT-12-SUMMARY.md) — Sprint 12 outcome (test infra delivered)
- [`.gitea/workflows/deploy.yml`](.gitea/workflows/deploy.yml) — Current CI/CD pipeline (no tests)
---
## 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 | **FIXED**`application.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`](.gitea/workflows/deploy.yml:17) 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
### Option C: Full Hardening Sprint (8-12 hours) ⬅️ RECOMMENDED
- 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)