Files
smoa/backend/docs/BACKEND-GAPS-AND-ROADMAP.md
defiQUG 5a8c26cf5d Backend, sync, infra, docs: ETag, API versioning, k8s, web scaffold, Android 16, domain stubs
- Backend: ShallowEtagHeaderFilter for /api/v1/*, API-VERSIONING.md, README (tenant, CORS, Flyway, ETag)
- k8s: backend-deployment.yaml (Deployment, Service, Secret/ConfigMap)
- Web: scaffold with directory pull, 304 handling, touch-friendly UI
- Android 16: ANDROID-16-TARGET.md; BuildConfig STUN/signaling, SMOAApplication configures InfrastructureManager
- Domain: CertificateManager revocation stub, ReportService signReports, ZeroTrust/ThreatDetection minimal docs
- TODO.md and IMPLEMENTATION_STATUS.md updated; communications README for endpoint config

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 20:37:01 -08:00

106 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SMOA Backend Gap Analysis and Roadmap
## Review summary
The backend implements the **sync contract** expected by the mobile app (POST sync endpoints, SyncResponse with conflict/remoteData), with **validation**, **optional API key auth**, **OpenAPI**, **conflict detection**, and **H2 persistence**. Below are covered areas, gaps, and recommendations.
---
## What's in place
| Area | Status |
|------|--------|
| **Sync API contract** | All five sync endpoints (directory, order, evidence, credential, report); request DTOs aligned with app; SyncResponse with success, itemId, serverTimestamp, conflict, remoteData, message. |
| **Conflict detection** | Directory uses lastUpdated; others use clientUpdatedAt; server returns conflict + remoteData when server has newer version. |
| **Validation** | @Valid on all sync bodies; NotBlank/NotNull on required fields. |
| **Auth** | Optional API key via X-API-Key or api_key query; when key is set, all /api/v1/* require it. |
| **Security** | Stateless; CSRF disabled for API; health/info/docs/h2-console permitted without auth. |
| **Persistence** | JPA entities and repositories for all five resource types; H2 file DB; ddl-auto: update. |
| **OpenAPI** | springdoc; /v3/api-docs, /swagger-ui.html; ApiKey scheme documented. |
| **Health** | GET /health with status, application, timestamp, and DB check (up/down). |
| **CORS** | Configurable via smoa.cors.allowed-origins (default *). |
| **Error handling** | Global exception handler: 400 for validation/type errors with JSON body; 500 for other errors. |
---
## Gaps and recommendations
### 1. **Delete / SyncOperation.Delete** ✅ Done
- **Gap:** App has SyncOperation.Create, Update, **Delete**. Backend only does upsert (create/update).
- **Done:** DELETE endpoints added: `/api/v1/sync/directory/{id}`, `/order/{orderId}`, `/evidence/{evidenceId}`, `/credential/{credentialId}`, `/report/{reportId}`; each returns SyncResponse; audit logged.
### 2. **Pull / GET (initial load or refresh)** ✅ Done
- **Gap:** No GET endpoints. App today only pushes from a queue; for "refresh after coming online" or initial load, pull is often needed.
- **Done:** GET list endpoints: `/api/v1/directory` (optional `unit`, `X-Unit`), `/api/v1/orders` (since, limit, jurisdiction / X-Unit), `/api/v1/evidence`, `/api/v1/credentials`, `/api/v1/reports` (since, limit, optional filters). See PullController and `api/dto/PullResponse.kt`.
### 3. **Enum validation** ✅ Done
- **Gap:** orderType, status (orders), evidenceType, reportType are free strings. App uses enums.
- **Done:** @Pattern added for orderType (AUTHORIZATION|…|ADMINISTRATIVE), status (DRAFT|…|REVOKED), evidenceType (PHYSICAL|…|DOCUMENT), reportType (OPERATIONAL|…|REGULATORY), report format (PDF|XML|JSON|CSV|EXCEL).
### 4. **SyncResponse.remoteData format** ✅ Done
- **Gap:** Backend returns remoteData as base64; client must decode.
- **Done:** Documented in OpenAPI description that remoteData is base64-encoded JSON when conflict=true.
### 5. **Production and ops**
- **Gap:** H2 console enabled in all profiles; no explicit prod profile with console off and stricter settings.
- **Recommendation:** Add application-prod.yml: disable H2 console, set logging, optionally require API key. Document PostgreSQL (or other DB) and env vars.
### 6. **Rate limiting** ✅ Done
- **Gap:** No rate limiting on sync or auth.
- **Done:** RateLimitFilter on /api/v1/*; per API key or IP; configurable `smoa.rate-limit.requests-per-minute` (default 120); 429 when exceeded; disabled in test profile.
### 7. **Audit / logging** ✅ Done
- **Gap:** No structured audit log for "who synced what when".
- **Done:** SyncAuditLog entity and SyncAuditService; sync and delete operations logged (resourceType, resourceId, operation, success). SyncController calls audit after each sync/delete.
### 8. **Tests** ✅ Done
- **Gap:** No backend unit or integration tests.
- **Done:** DirectorySyncServiceTest (create, conflict/remoteData, delete); GlobalExceptionHandlerTest (500); SyncControllerIntegrationTest (POST valid/invalid, health); application-test.yml (H2 in-memory, rate limit off); mockk for unit tests.
### 9. **Ids and authorization**
- **Gap:** No tenant/org/unit scoping; any client with a valid API key can read/write any resource.
- **Recommendation:** If the app is multi-tenant or unit-scoped, add unit/tenant to API key or token and filter queries (e.g. directory by unit, orders by unit).
### 10. **Infrastructure** ✅ Done (Dockerfile)
- **Gap:** No Dockerfile or k8s manifests; no migration strategy beyond ddl-auto.
- **Done:** backend/Dockerfile (multi-stage); build from repo root: `docker build -f backend/Dockerfile .`. Optional: Flyway/Liquibase and ddl-auto: validate in prod.
---
## Optional improvements
- **Pagination:** For any future GET list endpoints, use page/size or limit/offset and document in OpenAPI.
- **ETag / If-None-Match:** For GET-by-id or list endpoints, support caching with ETag.
- **Request ID:** Add a filter to assign and log a request ID for tracing.
- **API versioning:** Keep /api/v1; when introducing breaking changes, add /api/v2 and document deprecation.
---
## Quick reference: config
| Property | Default | Purpose |
|----------|---------|---------|
| smoa.api.key | (empty) | API key; empty = no auth |
| smoa.api.key-header | X-API-Key | Header name |
| smoa.cors.allowed-origins | * | CORS origins (comma-separated) |
| smoa.rate-limit.enabled | true | Enable rate limit on /api/v1/* |
| smoa.rate-limit.requests-per-minute | 120 | Max requests per key/IP per minute |
| server.port | 8080 | Port |
| spring.datasource.url | H2 file | DB URL (use PostgreSQL in prod) |
---
## Summary
The backend is **ready for mobile sync** with: push and **delete** sync, **pull/GET** endpoints, **conflict handling**, **enum validation**, **rate limiting**, **audit logging**, **tests**, and a **Dockerfile**. Remaining optional work: **prod profile and DB** (PostgreSQL, H2 console off), **unit/tenant scoping** (filter by unit from API key or header), and **migrations** (Flyway/Liquibase with ddl-auto: validate).