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
+524
View File
@@ -0,0 +1,524 @@
openapi: 3.0.3
info:
title: SMOA API Specification
description: |
API specification for Secure Mobile Operations Application (SMOA).
**Authoritative mobile sync contract:** the running backend’s OpenAPI document
(`/v3/api-docs` via springdoc) matches Kotlin DTOs in `backend/src/main/kotlin/.../api/dto`.
This YAML is a **design reference**; prefer springdoc export in CI if drift is detected.
Credential **sync** uses `CredentialSyncRequest` (POST `/api/v1/sync/credential`), not the
legacy `Credential` resource shape below where paths differ.
version: 1.0.0
contact:
name: SMOA Development Team
email: [email protected]
license:
name: Proprietary - Government Use Only
servers:
- url: https://api.smoa.example.com/v1
description: Production server
- url: https://api-dev.smoa.example.com/v1
description: Development server
tags:
- name: Authentication
description: Authentication and authorization endpoints
- name: Credentials
description: Digital credential management
- name: Orders
description: Orders management
- name: Evidence
description: Evidence chain of custody
- name: Reports
description: Report generation
- name: Communications
description: Secure communications
- name: Directory
description: Internal directory
security:
- BearerAuth: []
- ApiKeyAuth: []
paths:
/auth/login:
post:
tags:
- Authentication
summary: Authenticate user
description: |
Authenticate user with multi-factor authentication (PIN + Biometric).
Returns authentication token on success.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Authentication successful
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
'401':
description: Authentication failed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many login attempts
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/logout:
post:
tags:
- Authentication
summary: Logout user
description: Invalidates current session
responses:
'200':
description: Logout successful
'401':
description: Unauthorized
/credentials:
get:
tags:
- Credentials
summary: List user credentials
description: Returns list of credentials available to the authenticated user
parameters:
- name: type
in: query
schema:
type: string
enum: [id, badge, license, permit, other]
description: Filter by credential type
responses:
'200':
description: List of credentials
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Credential'
'401':
description: Unauthorized
post:
tags:
- Credentials
summary: Create new credential
description: Creates a new digital credential
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CredentialCreate'
responses:
'201':
description: Credential created
content:
application/json:
schema:
$ref: '#/components/schemas/Credential'
'400':
description: Invalid request
'401':
description: Unauthorized
/credentials/{id}:
get:
tags:
- Credentials
summary: Get credential by ID
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Credential ID
responses:
'200':
description: Credential details
content:
application/json:
schema:
$ref: '#/components/schemas/Credential'
'404':
description: Credential not found
'401':
description: Unauthorized
/orders:
get:
tags:
- Orders
summary: List orders
description: Returns list of orders available to the authenticated user
parameters:
- name: status
in: query
schema:
type: string
enum: [draft, pending_approval, approved, issued, executed, expired, revoked]
description: Filter by order status
- name: type
in: query
schema:
type: string
enum: [authorization, assignment, search_warrant, arrest_warrant, court_order, administrative]
description: Filter by order type
responses:
'200':
description: List of orders
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Order'
'401':
description: Unauthorized
post:
tags:
- Orders
summary: Create new order
description: Creates a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderCreate'
responses:
'201':
description: Order created
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Invalid request
'401':
description: Unauthorized
/orders/{id}:
get:
tags:
- Orders
summary: Get order by ID
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Order ID
responses:
'200':
description: Order details
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'404':
description: Order not found
'401':
description: Unauthorized
/evidence:
get:
tags:
- Evidence
summary: List evidence items
description: Returns list of evidence items
responses:
'200':
description: List of evidence items
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Evidence'
'401':
description: Unauthorized
/reports:
post:
tags:
- Reports
summary: Generate report
description: Generates a report in the specified format
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ReportRequest'
responses:
'200':
description: Report generated
content:
application/pdf:
schema:
type: string
format: binary
application/json:
schema:
type: string
application/xml:
schema:
type: string
text/csv:
schema:
type: string
'400':
description: Invalid request
'401':
description: Unauthorized
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
schemas:
LoginRequest:
type: object
required:
- pin
- biometricToken
properties:
pin:
type: string
description: User PIN
minLength: 6
maxLength: 12
biometricToken:
type: string
description: Biometric authentication token
LoginResponse:
type: object
properties:
token:
type: string
description: Authentication token
expiresIn:
type: integer
description: Token expiration time in seconds
user:
$ref: '#/components/schemas/User'
User:
type: object
properties:
id:
type: string
username:
type: string
roles:
type: array
items:
type: string
Credential:
type: object
properties:
id:
type: string
type:
type: string
description: >
Canonical values align with Complete Credential CredentialRef.domain plus
SMOA barcode templates (see docs/reference/IDENTITY-TEMPLATE-ALIGNMENT.md).
enum:
- piv_pki
- payment
- nfc_access
- mobile
- icao9303_mrtd
- aamva_dlid
- mil_std_129
- agency_badge
- id
- badge
- license
- permit
- other
title:
type: string
issuer:
type: string
issueDate:
type: string
format: date
expirationDate:
type: string
format: date
status:
type: string
enum: [active, expired, revoked]
barcode:
type: string
description: PDF417 barcode data
CredentialCreate:
type: object
required:
- type
- title
- issuer
properties:
type:
type: string
title:
type: string
issuer:
type: string
issueDate:
type: string
format: date
expirationDate:
type: string
format: date
CredentialSyncRequest:
type: object
required:
- credentialId
- holderId
- credentialType
description: >
Mobile sync body for POST /api/v1/sync/credential. credentialType matches
SmoaCredentialType (canonical + legacy). payload is optional JSON validated
per docs/schemas when issuing ICAO/AAMVA/military document types.
properties:
credentialId:
type: string
holderId:
type: string
credentialType:
type: string
pattern: ^(piv_pki|payment|nfc_access|mobile|icao9303_mrtd|aamva_dlid|mil_std_129|agency_badge|id|badge|license|permit|other)$
issuer:
type: string
issuedAt:
type: integer
format: int64
expiresAt:
type: integer
format: int64
payload:
type: object
additionalProperties: true
clientUpdatedAt:
type: integer
format: int64
Order:
type: object
properties:
id:
type: string
type:
type: string
enum: [authorization, assignment, search_warrant, arrest_warrant, court_order, administrative]
title:
type: string
status:
type: string
enum: [draft, pending_approval, approved, issued, executed, expired, revoked]
issuedBy:
type: string
issueDate:
type: string
format: date-time
expirationDate:
type: string
format: date-time
OrderCreate:
type: object
required:
- type
- title
properties:
type:
type: string
title:
type: string
content:
type: string
expirationDate:
type: string
format: date-time
Evidence:
type: object
properties:
id:
type: string
caseNumber:
type: string
description:
type: string
type:
type: string
enum: [physical, digital, biological, chemical, firearm, document]
collectionDate:
type: string
format: date-time
currentCustodian:
type: string
ReportRequest:
type: object
required:
- template
- format
properties:
template:
type: string
description: Report template name
format:
type: string
enum: [pdf, xml, json, csv]
parameters:
type: object
description: Template parameters
ErrorResponse:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
timestamp:
type: string
format: date-time
+13
View File
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SMOA API — ReDoc</title>
<style>body { margin: 0; }</style>
</head>
<body>
<redoc spec-url="./api-specification.yaml"></redoc>
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"></script>
</body>
</html>