diff --git a/README.md b/README.md new file mode 100644 index 0000000..28aca6b --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# CannaManage + +Multi-tenant cannabis club management platform for German **Anbauvereinigungen** (cultivation associations) under CanG §19. + +## Overview + +CannaManage handles member management, distribution tracking, and legal compliance for cannabis cultivation clubs in Germany. It enforces the strict quotas mandated by the Cannabis Act (CanG) — including monthly limits (50g adult / 30g under-21), daily limits (25g), and THC restrictions for minors. + +## Tech Stack + +| Component | Technology | +|-----------|-----------| +| Runtime | Java 21 (Temurin) | +| Framework | Spring Boot 4.0.6 | +| Security | Spring Security 7.0 + JWT (JJWT 0.12.6) | +| ORM | Hibernate 7 / JPA | +| Database | PostgreSQL (prod), H2 (test) | +| Migrations | Flyway 10 | +| API Docs | SpringDoc OpenAPI 2.8.6 | +| Build | Maven (multi-module) | +| Container | Docker Compose (Postgres + app) | + +## Project Structure + +``` +cannamanage/ +├── cannamanage-domain/ # JPA entities, enums, TenantContext +├── cannamanage-service/ # Business logic, repositories, ComplianceService +├── cannamanage-api/ # Spring Boot app, controllers, security, DTOs +├── docs/ +│ └── sprint-2/ # Sprint planning docs +└── docker-compose.yml # Local dev environment +``` + +## Modules + +### cannamanage-domain +JPA entities with multi-tenant isolation via `@Filter("tenantFilter")`: +- `Member` — club members with age tracking +- `Distribution` — cannabis distribution records +- `MonthlyQuota` — per-member monthly usage tracking +- `Batch` / `Strain` / `StockMovement` — inventory management +- `Club` — association registration +- `User` — authentication accounts + +### cannamanage-service +- `ComplianceService` — CanG §19 quota enforcement (25 unit tests) +- Repositories for all entities + +### cannamanage-api +- **Auth** — JWT login + refresh token rotation (SHA-256 hashed) +- **Members** — CRUD for association members +- **Distributions** — compliance-gated distribution recording +- **Stock** — batch and inventory management +- **Compliance** — quota status API +- Multi-tenant isolation via `TenantFilterAspect` (Hibernate @Filter activation) + +## API Endpoints + +| Method | Path | Auth | Description | +|--------|------|------|-------------| +| POST | `/api/v1/auth/login` | Public | Login with email + password | +| POST | `/api/v1/auth/refresh` | Public | Refresh token rotation | +| GET | `/api/v1/compliance/quota/{memberId}` | ADMIN, MEMBER | Monthly quota status | +| GET/POST/PUT | `/api/v1/members/**` | ADMIN, MEMBER | Member CRUD | +| POST | `/api/v1/distributions/**` | ADMIN, MEMBER | Record distributions | +| GET/POST | `/api/v1/stock/**` | ADMIN | Stock management | + +Swagger UI: `http://localhost:8080/swagger-ui.html` + +## Running Locally + +```bash +# Start PostgreSQL +docker compose up -d + +# Run the app +JAVA_HOME=/path/to/jdk-21 ./mvnw spring-boot:run -pl cannamanage-api + +# Run all tests (H2 in-memory) +JAVA_HOME=/path/to/jdk-21 ./mvnw clean verify +``` + +## Testing + +- **37 tests total** — all green +- 25 unit tests (`ComplianceServiceTest`) — quota enforcement logic +- 7 integration tests (`AuthControllerIntegrationTest`) — full HTTP auth flow +- 5 integration tests (`ComplianceControllerIntegrationTest`) — quota API with JWT + +Integration tests use `@SpringBootTest(webEnvironment = RANDOM_PORT)` with H2 and Spring's `RestClient`. + +## Security Model + +- **Stateless JWT** — no session, no UserDetailsService +- **Roles**: ADMIN (full access), MEMBER (self-service), STAFF (Sprint 3) +- **Multi-tenancy**: Hibernate `@Filter` activated per-request via AOP aspect +- **Refresh tokens**: SHA-256 hashed (Spring Security 7 enforces BCrypt 72-byte limit) +- Token rotation on refresh — old tokens invalidated + +## Sprint History + +| Sprint | Focus | Status | +|--------|-------|--------| +| 1 | Domain entities, ComplianceService, 25 tests | ✅ Done | +| 2 | REST API, Spring Security, JWT, OpenAPI, integration tests | ✅ Done | +| 3 | Member portal, STAFF role, real-time notifications | 📋 Planned | + +## License + +Private — Patrick Plate