- 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
222 lines
6.8 KiB
Markdown
222 lines
6.8 KiB
Markdown
# SMOA database schema (server + device)
|
|
|
|
**Version:** 2.0
|
|
**Last updated:** 2026-03-23
|
|
|
|
This document aligns **SMOA backend** (Flyway `V1__baseline.sql`, H2 or PostgreSQL) with **on-device Room** entities in this repository. Older rows that described only a generic local `credentials` table **without** a matching entity are removed.
|
|
|
|
---
|
|
|
|
## 1. Server database (SMOA backend)
|
|
|
|
Source of truth: `backend/src/main/resources/db/migration/V1__baseline.sql`.
|
|
JPA entities: `backend/src/main/kotlin/com/smoa/backend/domain/*.kt`.
|
|
|
|
### 1.1 `directory_entries`
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| id | VARCHAR(255) PK | Directory entry id |
|
|
| name | VARCHAR(255) | Display name |
|
|
| title | VARCHAR(255) | Job title |
|
|
| unit | VARCHAR(255) | Unit / org |
|
|
| phone_number | VARCHAR(255) | Phone |
|
|
| extension | VARCHAR(255) | Extension |
|
|
| email | VARCHAR(255) | Email |
|
|
| secure_routing_id | VARCHAR(255) | Secure routing |
|
|
| role | VARCHAR(255) | Role |
|
|
| clearance_level | VARCHAR(255) | Clearance |
|
|
| last_updated | BIGINT | Epoch ms |
|
|
|
|
### 1.2 `orders`
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| order_id | VARCHAR(255) PK | Order id |
|
|
| order_type | VARCHAR(255) | Enum string (see backend validation) |
|
|
| title | VARCHAR(255) | Title |
|
|
| content | CLOB | Body |
|
|
| issued_by | VARCHAR(255) | Issuer |
|
|
| issued_to | VARCHAR(255) | Recipient |
|
|
| issue_date | TIMESTAMP | Issued |
|
|
| effective_date | TIMESTAMP | Effective |
|
|
| expiration_date | TIMESTAMP | Expiry |
|
|
| status | VARCHAR(255) | Status enum |
|
|
| classification | VARCHAR(255) | Classification |
|
|
| jurisdiction | VARCHAR(255) | Jurisdiction |
|
|
| case_number | VARCHAR(255) | Case |
|
|
| updated_at | BIGINT | Epoch ms |
|
|
|
|
### 1.3 `evidence`
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| evidence_id | VARCHAR(255) PK | Evidence id |
|
|
| case_number | VARCHAR(255) | Case |
|
|
| description | CLOB | Description |
|
|
| evidence_type | VARCHAR(255) | Type enum |
|
|
| collection_date | TIMESTAMP | Collected |
|
|
| collection_location | VARCHAR(255) | Location |
|
|
| collection_method | VARCHAR(255) | Method |
|
|
| collected_by | VARCHAR(255) | Collector |
|
|
| current_custodian | VARCHAR(255) | Custodian |
|
|
| storage_location | VARCHAR(255) | Storage |
|
|
| updated_at | BIGINT | Epoch ms |
|
|
|
|
### 1.4 `credentials` (server)
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| credential_id | VARCHAR(255) PK | Credential id |
|
|
| holder_id | VARCHAR(255) | Subject / holder |
|
|
| credential_type | VARCHAR(255) | Canonical type (`SmoaCredentialType` + legacy; see `docs/reference/IDENTITY-TEMPLATE-ALIGNMENT.md`) |
|
|
| issuer | VARCHAR(255) | Issuing authority label |
|
|
| issued_at | BIGINT | Epoch ms (optional) |
|
|
| expires_at | BIGINT | Epoch ms (optional) |
|
|
| payload_json | CLOB | JSON object: format-specific fields, optional `issuingAuthority`, `completeCredentialDomain`, `extensions` |
|
|
| updated_at | BIGINT | Epoch ms |
|
|
|
|
**Issuance validation:** Parse `payload_json` as JSON, then validate with `docs/schemas/credential-payload-*.schema.json` for the given `credential_type` on the sync **request body** (not duplicated inside payload).
|
|
|
|
### 1.5 `reports`
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| report_id | VARCHAR(255) PK | Report id |
|
|
| report_type | VARCHAR(255) | Type enum |
|
|
| title | VARCHAR(255) | Title |
|
|
| format | VARCHAR(255) | PDF, XML, JSON, CSV, EXCEL |
|
|
| generated_date | BIGINT | Epoch ms |
|
|
| generated_by | VARCHAR(255) | Generator |
|
|
| content | BLOB | Optional binary |
|
|
| metadata_json | CLOB | Optional JSON |
|
|
| updated_at | BIGINT | Epoch ms |
|
|
|
|
### 1.6 `sync_audit_log`
|
|
|
|
| Column | SQL type | Description |
|
|
|--------|-----------|-------------|
|
|
| id | BIGINT IDENTITY PK | Surrogate key |
|
|
| resource_type | VARCHAR(255) | Resource |
|
|
| resource_id | VARCHAR(255) | Id |
|
|
| operation | VARCHAR(255) | Operation |
|
|
| success | BOOLEAN | Outcome |
|
|
| principal | VARCHAR(255) | Optional actor |
|
|
| timestamp | TIMESTAMP | Event time |
|
|
|
|
---
|
|
|
|
## 2. On-device Room (implemented modules)
|
|
|
|
Room uses SQLite; module-specific databases. Below match Kotlin `@Entity` types.
|
|
|
|
### 2.1 Directory — `directory_entries`
|
|
|
|
`modules/directory/.../DirectoryEntity.kt`
|
|
|
|
| Column | Type | Notes |
|
|
|--------|------|--------|
|
|
| id | TEXT PK | |
|
|
| name | TEXT | |
|
|
| title | TEXT? | |
|
|
| unit | TEXT | |
|
|
| phoneNumber | TEXT? | camelCase in Kotlin → snake in DB per Room |
|
|
| extension | TEXT? | |
|
|
| email | TEXT? | |
|
|
| secureRoutingId | TEXT? | |
|
|
| role | TEXT? | |
|
|
| clearanceLevel | TEXT? | |
|
|
| lastUpdated | INTEGER | Epoch ms |
|
|
|
|
### 2.2 Orders — `orders`
|
|
|
|
`modules/orders/.../OrderEntity.kt`
|
|
|
|
| Column | Type | Notes |
|
|
|--------|------|--------|
|
|
| orderId | TEXT PK | |
|
|
| orderType | TEXT | Enum persisted via converter |
|
|
| title | TEXT | |
|
|
| content | TEXT | |
|
|
| issuedBy | TEXT | |
|
|
| issuedTo | TEXT? | |
|
|
| issueDate | INTEGER / Date | Type converters |
|
|
| effectiveDate | | |
|
|
| expirationDate | | |
|
|
| status | | Enum |
|
|
| classification | TEXT? | |
|
|
| jurisdiction | TEXT | |
|
|
| caseNumber | TEXT? | |
|
|
| createdAt | | |
|
|
| updatedAt | | |
|
|
|
|
### 2.3 Evidence — `evidence`
|
|
|
|
`modules/evidence/.../EvidenceEntity.kt`
|
|
|
|
| Column | Type | Notes |
|
|
|--------|------|--------|
|
|
| evidenceId | TEXT PK | |
|
|
| caseNumber | TEXT | |
|
|
| description | TEXT | |
|
|
| evidenceType | | Enum |
|
|
| collectionDate | | |
|
|
| collectionLocation | TEXT | |
|
|
| collectionMethod | TEXT | |
|
|
| collectedBy | TEXT | |
|
|
| currentCustodian | TEXT | |
|
|
| storageLocation | TEXT? | |
|
|
| createdAt | | |
|
|
| updatedAt | | |
|
|
|
|
### 2.4 Custody — `custody_transfers`
|
|
|
|
`modules/evidence/.../CustodyTransferEntity.kt`
|
|
|
|
| Column | Type | Notes |
|
|
|--------|------|--------|
|
|
| transferId | TEXT PK | |
|
|
| evidenceId | TEXT FK → evidence | |
|
|
| timestamp | Date | |
|
|
| fromCustodian | TEXT | |
|
|
| toCustodian | TEXT | |
|
|
| reason | TEXT | |
|
|
| evidenceCondition | TEXT | |
|
|
| signatureData | BLOB? | |
|
|
| notes | TEXT? | |
|
|
|
|
### 2.5 Credentials cache — `credential_cache`
|
|
|
|
`modules/credentials/.../CredentialCacheEntity.kt` (encrypted Room DB `credential_cache_database`)
|
|
|
|
| Column | Type | Notes |
|
|
|--------|------|--------|
|
|
| credentialId | TEXT PK | |
|
|
| holderId | TEXT | |
|
|
| credentialType | TEXT | |
|
|
| issuer | TEXT? | |
|
|
| issuedAt | INTEGER? | Epoch ms |
|
|
| expiresAt | INTEGER? | Epoch ms |
|
|
| payloadJson | TEXT? | JSON string |
|
|
| updatedAt | INTEGER | Epoch ms |
|
|
|
|
Populate from pull/sync merge logic in application code when wired; schema matches server `credentials` for offline display.
|
|
|
|
### 2.6 Reports (device)
|
|
|
|
No Room `ReportEntity` in this repo; reports remain server-backed unless a local entity is added later.
|
|
|
|
---
|
|
|
|
## 3. Indexes (server)
|
|
|
|
- `idx_sync_audit_timestamp` on `sync_audit_log(timestamp)`
|
|
|
|
---
|
|
|
|
## 4. References
|
|
|
|
- Backend Flyway: `backend/src/main/resources/db/migration/V1__baseline.sql`
|
|
- Identity / payload schemas: `docs/reference/IDENTITY-TEMPLATE-ALIGNMENT.md`, `docs/schemas/`
|
|
- Tenant model: `docs/security/TENANT-THREAT-MODEL.md`
|