Files
smoa/backend/docs/BACKEND-GAPS-AND-ROADMAP.md
T
defiQUG a2dc194a49 Monorepo: Gitea CI, docs, auth/sync, backend APIs, gitignore
- Add Gitea Actions workflow; point README to gitea.d-bis.org/Sankofa_Phoenix/SMOA
- Expand .gitignore for Spring H2 data, secrets, Kotlin .kotlin/, tooling
- Track docs/api/generated ReDoc bundle; refresh api docs README
- Android: network/auth/sync, UI shell, tests; backend credentials/integrity APIs
- Docs, scripts (generate-api-docs), modules and core updates

Made-with: Cursor
2026-03-23 20:19:24 -07:00

6.3 KiB
Raw Blame History

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 ✅ Done (baseline)

  • Done: application-prod.yml disables H2 console, sets ddl-auto: validate, Flyway on, stricter logging.
  • Done: org.postgresql:postgresql on the runtime classpath; set SPRING_DATASOURCE_* (see application-prod.yml and backend README) for PostgreSQL. Dev/test keep H2 unless overridden.

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 (directory, credential type validation, 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: Pull endpoints use limit/since; extend with cursor or page/size if lists grow very large.
  • ETag / If-None-Match: ✅ ShallowEtagHeaderFilter on /api/v1/** (see WebConfig).
  • Request ID: ✅ RequestIdFilter assigns/propagates X-Request-Id.
  • API versioning: Keep /api/v1; when introducing breaking changes, add /api/v2 and document deprecation.
  • Credential types: ✅ @Pattern on CredentialSyncRequest.credentialType (SmoaCredentialType.CREDENTIAL_TYPE_PATTERN).

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 (with ETag), conflict handling, enum validation (including credential types), rate limiting, audit logging, request IDs, tests, Dockerfile, prod profile, PostgreSQL driver, and Flyway with ddl-auto: validate in prod. Remaining: strong tenant isolation (per-tenant credentials, RLS, or JWT claims) — see docs/security/TENANT-THREAT-MODEL.md.