core PK: id 10 required 1 unique

Description

Formal signed record of a peer mentor or driver's confidentiality obligation, required for specific expense claim types (e.g. driver honoraria) before a claim can be submitted. Captures the declaration content, digital signature, validity period, and linkage to the associated expense claim.

17
Attributes
4
Indexes
6
Validation Rules
11
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Surrogate primary key, generated server-side on creation
PKrequiredunique
expense_claim_id uuid Foreign key to the expense_claims row this declaration is attached to. A single expense claim may have at most one active declaration at a time.
required
user_id uuid Foreign key to the users row of the peer mentor or driver who signed the declaration. Denormalized for fast audit queries independent of the expense claim.
required
organization_id uuid Tenant scoping key. All queries are filtered by organization_id to enforce tenant isolation.
required
declaration_type enum Category of confidentiality obligation. 'driver_confidentiality' covers peer mentors acting as drivers who handle sensitive personal information about contacts. 'general_confidentiality' is a catch-all for other organization-defined cases.
required
declaration_text text Full canonical text of the confidentiality obligation at the time of signing. Stored verbatim so the signed content is immutable even if the organization later changes its template.
required
status enum Lifecycle state of the declaration. 'pending' = presented to user but not yet signed. 'signed' = user accepted and signature recorded. 'expired' = valid_until passed. 'revoked' = administratively invalidated.
required
signature_method enum How the user confirmed acceptance. 'in_app_tap' = tapped 'I agree' button. 'biometric' = biometric confirmation used as signing gesture. Recorded for audit purposes.
required
signed_at datetime UTC timestamp of when the user completed the signing gesture. Null while status is 'pending'.
-
valid_from datetime UTC datetime from which this declaration is considered active. Defaults to signed_at. Allows organizations to backdate declarations to the start of a claim period.
-
valid_until datetime UTC datetime after which the declaration expires. Null means the declaration does not expire by time (only by revocation). Organizations may configure a rolling validity window (e.g. calendar year).
-
device_fingerprint string Hashed identifier of the device on which the declaration was signed (Flutter device_info_plus output, SHA-256). Used in audit trail to confirm signing was performed on a known device.
-
ip_address string IP address of the client at time of signing, recorded for audit. May be absent in offline-first scenarios where signing happens while disconnected; populated on first successful sync.
-
revocation_reason text Free-text reason provided by an administrator when revoking the declaration. Null unless status is 'revoked'.
-
revoked_by uuid user_id of the administrator who revoked the declaration. Null unless status is 'revoked'.
-
created_at datetime UTC timestamp of row insertion. Set by the database on INSERT, never updated.
required
updated_at datetime UTC timestamp of last modification. Updated by trigger or application on every UPDATE.
required

Database Indexes

idx_declarations_expense_claim_id
btree

Columns: expense_claim_id

idx_declarations_user_id_status
btree

Columns: user_id, status

idx_declarations_organization_id_created_at
btree

Columns: organization_id, created_at

idx_declarations_status_valid_until
btree

Columns: status, valid_until

Validation Rules

declaration_text_not_empty error

Validation failed

valid_until_after_valid_from error

Validation failed

signed_at_required_when_signed error

Validation failed

revocation_reason_required_when_revoked error

Validation failed

expense_claim_must_exist error

Validation failed

organization_tenant_match error

Validation failed

Business Rules

declaration_required_before_claim_submission
on_update

An expense claim of type 'driver_honoraria' or any type flagged as requiring a declaration by the organization's expense type configuration cannot transition from 'draft' to 'submitted' unless a linked declaration row exists with status 'signed'.

declaration_immutable_after_signing
on_update

Once status transitions to 'signed', the fields declaration_text, signature_method, signed_at, and valid_from become read-only. Any UPDATE attempt on these columns for a signed row must be rejected.

Enforced by: Declaration Service
single_active_declaration_per_claim
on_create

At most one declaration with status 'pending' or 'signed' may exist for a given expense_claim_id at any time. Attempting to create a second active declaration for the same claim must be rejected unless the previous one is first revoked or expired.

Enforced by: Declaration Service
revocation_requires_admin_role
on_update

Only users with role 'coordinator', 'org_admin', or 'global_admin' may set status to 'revoked'. Peer mentors cannot revoke their own declarations.

expiry_auto_transition
always

A scheduled job evaluates all signed declarations where valid_until < NOW() and transitions their status from 'signed' to 'expired'. Affected expense claims that are still in 'draft' are flagged, triggering a notification to the peer mentor.

audit_log_on_all_state_changes
on_update

Every status transition (pending→signed, signed→expired, signed→revoked) must produce an audit_logs entry referencing the declaration id, the actor user_id, the old and new status, and a UTC timestamp.

offline_signing_sync_integrity
on_create

Declarations signed while the device is offline are held in the mutation outbox. On sync, the server validates that the associated expense_claim_id still exists and has not been cancelled before persisting the declaration. If validation fails, the mutation is rejected and the peer mentor is notified.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage