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
This commit is contained in:
defiQUG
2026-03-23 20:19:24 -07:00
parent f97e23592c
commit a2dc194a49
234 changed files with 10008 additions and 1149 deletions
+203 -280
View File
@@ -1,298 +1,221 @@
# SMOA Database Schema Documentation
# SMOA database schema (server + device)
**Version:** 1.0
**Last Updated:** 2024-12-20
**Status:** Draft - In Progress
**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.
---
## Database Overview
## 1. Server database (SMOA backend)
### Database Technology
- **Database:** SQLite (via Room)
- **Version:** SQLite 3.x
- **Location:** Local device storage
- **Encryption:** AES-256-GCM encryption
Source of truth: `backend/src/main/resources/db/migration/V1__baseline.sql`.
JPA entities: `backend/src/main/kotlin/com/smoa/backend/domain/*.kt`.
### Database Purpose
SMOA uses Room database for local data storage, providing:
- Offline data access
- Fast local queries
- Encrypted data storage
- Data synchronization support
### 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 |
---
## Schema Diagrams
## 2. On-device Room (implemented modules)
### Entity Relationship Diagram
[To be added: ER diagram showing all entities and relationships]
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.
---
## Tables
## 3. Indexes (server)
### User Table
#### Table: users
- **Purpose:** Store user information
- **Primary Key:** user_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| user_id | TEXT | PRIMARY KEY | Unique user identifier |
| username | TEXT | NOT NULL, UNIQUE | Username |
| email | TEXT | | Email address |
| role | TEXT | NOT NULL | User role |
| created_at | INTEGER | NOT NULL | Creation timestamp |
| updated_at | INTEGER | NOT NULL | Update timestamp |
### Credential Table
#### Table: credentials
- **Purpose:** Store digital credentials
- **Primary Key:** credential_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| credential_id | TEXT | PRIMARY KEY | Unique credential identifier |
| user_id | TEXT | NOT NULL, FOREIGN KEY | User who owns credential |
| type | TEXT | NOT NULL | Credential type |
| title | TEXT | NOT NULL | Credential title |
| issuer | TEXT | NOT NULL | Issuing authority |
| issue_date | INTEGER | | Issue date (Unix timestamp) |
| expiration_date | INTEGER | | Expiration date |
| status | TEXT | NOT NULL | Status (active, expired, revoked) |
| barcode_data | TEXT | | PDF417 barcode data |
| created_at | INTEGER | NOT NULL | Creation timestamp |
| updated_at | INTEGER | NOT NULL | Update timestamp |
**Foreign Keys:**
- user_id → users(user_id)
### Order Table
#### Table: orders
- **Purpose:** Store digital orders
- **Primary Key:** order_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| order_id | TEXT | PRIMARY KEY | Unique order identifier |
| order_type | TEXT | NOT NULL | Order type |
| title | TEXT | NOT NULL | Order title |
| content | TEXT | NOT NULL | Order content |
| issued_by | TEXT | NOT NULL | Issuing authority |
| issued_to | TEXT | | Recipient |
| issue_date | INTEGER | NOT NULL | Issue date |
| effective_date | INTEGER | NOT NULL | Effective date |
| expiration_date | INTEGER | | Expiration date |
| status | TEXT | NOT NULL | Order status |
| created_at | INTEGER | NOT NULL | Creation timestamp |
| updated_at | INTEGER | NOT NULL | Update timestamp |
### Evidence Table
#### Table: evidence
- **Purpose:** Store evidence items
- **Primary Key:** evidence_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| evidence_id | TEXT | PRIMARY KEY | Unique evidence identifier |
| case_number | TEXT | NOT NULL | Case number |
| description | TEXT | NOT NULL | Evidence description |
| type | TEXT | NOT NULL | Evidence type |
| collection_date | INTEGER | NOT NULL | Collection date |
| collection_location | TEXT | | Collection location |
| collected_by | TEXT | NOT NULL | Collector |
| current_custodian | TEXT | NOT NULL | Current custodian |
| storage_location | TEXT | | Storage location |
| created_at | INTEGER | NOT NULL | Creation timestamp |
| updated_at | INTEGER | NOT NULL | Update timestamp |
### Custody Transfer Table
#### Table: custody_transfers
- **Purpose:** Track evidence custody transfers
- **Primary Key:** transfer_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| transfer_id | TEXT | PRIMARY KEY | Unique transfer identifier |
| evidence_id | TEXT | NOT NULL, FOREIGN KEY | Evidence item |
| from_custodian | TEXT | NOT NULL | Transferring custodian |
| to_custodian | TEXT | NOT NULL | Receiving custodian |
| transfer_date | INTEGER | NOT NULL | Transfer date |
| reason | TEXT | | Transfer reason |
| evidence_condition | TEXT | | Evidence condition |
| signature | TEXT | | Digital signature |
| created_at | INTEGER | NOT NULL | Creation timestamp |
**Foreign Keys:**
- evidence_id → evidence(evidence_id)
### Report Table
#### Table: reports
- **Purpose:** Store generated reports
- **Primary Key:** report_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| report_id | TEXT | PRIMARY KEY | Unique report identifier |
| template | TEXT | NOT NULL | Report template |
| format | TEXT | NOT NULL | Report format (PDF, XML, JSON, CSV) |
| parameters | TEXT | | Report parameters (JSON) |
| generated_by | TEXT | NOT NULL | Generator user |
| generated_at | INTEGER | NOT NULL | Generation timestamp |
| file_path | TEXT | | Report file path |
| file_size | INTEGER | | File size in bytes |
### Audit Log Table
#### Table: audit_logs
- **Purpose:** Store audit trail records
- **Primary Key:** log_id
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| log_id | TEXT | PRIMARY KEY | Unique log identifier |
| event_type | TEXT | NOT NULL | Event type |
| user_id | TEXT | | User who triggered event |
| module | TEXT | | Module where event occurred |
| action | TEXT | NOT NULL | Action performed |
| resource | TEXT | | Resource affected |
| result | TEXT | NOT NULL | Result (success, failure) |
| details | TEXT | | Additional details (JSON) |
| timestamp | INTEGER | NOT NULL | Event timestamp |
| ip_address | TEXT | | IP address (if applicable) |
- `idx_sync_audit_timestamp` on `sync_audit_log(timestamp)`
---
## Indexes
### Performance Indexes
- **users(username):** Index on username for login
- **credentials(user_id):** Index on user_id for user credential queries
- **credentials(status):** Index on status for status queries
- **orders(status):** Index on order status
- **orders(order_type):** Index on order type
- **evidence(case_number):** Index on case number
- **audit_logs(timestamp):** Index on timestamp for time-based queries
- **audit_logs(user_id):** Index on user_id for user audit queries
---
## Data Dictionary
### Data Elements
#### User Data Elements
- **user_id:** Unique identifier for users
- **username:** User login name
- **role:** User role (administrator, operator, viewer, auditor)
#### Credential Data Elements
- **credential_id:** Unique identifier for credentials
- **type:** Credential type (id, badge, license, permit, other)
- **status:** Credential status (active, expired, revoked)
#### Order Data Elements
- **order_id:** Unique identifier for orders
- **order_type:** Order type (authorization, assignment, search_warrant, etc.)
- **status:** Order status (draft, pending_approval, approved, issued, etc.)
#### Evidence Data Elements
- **evidence_id:** Unique identifier for evidence
- **type:** Evidence type (physical, digital, biological, chemical, firearm, document)
- **current_custodian:** Current custodian of evidence
---
## Migrations
### Migration History
#### Migration 1: Initial Schema
- **Version:** 1
- **Date:** 2024-01-01
- **Description:** Initial database schema creation
#### Migration 2: Add Audit Logging
- **Version:** 2
- **Date:** 2024-02-01
- **Description:** Add audit log table and indexes
### Migration Procedures
#### Applying Migrations
1. **Backup Database:** Backup current database
2. **Review Migration:** Review migration script
3. **Test Migration:** Test migration in staging
4. **Apply Migration:** Apply migration to production
5. **Verify Migration:** Verify migration success
#### Rollback Procedures
1. **Identify Migration:** Identify migration to rollback
2. **Backup Current:** Backup current database
3. **Restore Previous:** Restore previous database version
4. **Verify Rollback:** Verify rollback success
---
## Data Protection
### Encryption
- **At Rest:** AES-256-GCM encryption
- **Key Storage:** Hardware-backed key storage
- **Key Management:** Automatic key rotation
### Access Control
- **Database Access:** Application-only access
- **User Access:** Role-based data access
- **Audit Logging:** All access logged
---
## Backup and Recovery
### Backup Procedures
- **Automated Backups:** Daily automated backups
- **Backup Location:** Encrypted backup storage
- **Backup Retention:** 90 days
### Recovery Procedures
- **Full Recovery:** Complete database restoration
- **Partial Recovery:** Selective data restoration
- **Point-in-Time Recovery:** Recovery to specific point
---
## Performance Optimization
### Query Optimization
- **Indexes:** Strategic index placement
- **Query Tuning:** Optimized queries
- **Caching:** Query result caching
### Database Maintenance
- **Vacuum:** Regular database vacuum
- **Analyze:** Regular statistics update
- **Optimization:** Periodic optimization
---
## References
- [Architecture Documentation](../architecture/ARCHITECTURE.md)
- [Administrator Guide](../admin/SMOA-Administrator-Guide.md)
- [Backup and Recovery Procedures](../operations/SMOA-Backup-Recovery-Procedures.md)
---
**Document Owner:** Database Administrator
**Last Updated:** 2024-12-20
**Status:** Draft - In Progress
**Next Review:** 2024-12-27
## 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`