Activity
Data Entity
Description
The primary operational record capturing a single peer mentor activity registration. Each activity records the type, date, duration, associated contact, and summary, forming the foundation for all Bufdir grant reporting, personal statistics, and coordinator oversight.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Immutable primary key generated at record creation. Used as the stable reference across all related tables (activity_logs, activity_documents, delegation_grants, bulk_registrations). | PKrequiredunique |
user_id |
uuid |
FK to users. Identifies the peer mentor who performed the activity. In proxy and bulk registrations this is the target peer mentor, not the coordinator who submitted the record. | required |
organization_id |
uuid |
FK to organizations. Scopes the activity to a specific member organization for Supabase RLS enforcement, Bufdir report attribution, and cross-org duplicate prevention. | required |
activity_type_id |
uuid |
FK to activity_types. Identifies the organization-specific activity category (e.g., home visit, phone call, group session). Drives conditional field visibility, Bufdir categorization, and validation rules. | required |
contact_id |
uuid |
FK to contacts. References the individual who received peer mentor support. Nullable for group or event-based activities where no single contact is the recipient. | - |
activity_date |
datetime |
Date and time when the activity took place. Used as the primary temporal dimension for Bufdir reporting period attribution, personal statistics, duplicate detection, and coordinator dashboard aggregations. | required |
duration_minutes |
integer |
Duration of the activity in minutes. Pre-populated from user default values (HLF default: 30 min). Used in Bufdir hour aggregations, personal statistics, and honorarium threshold calculations. | required |
summary |
text |
Free-text narrative summary of the activity written by the peer mentor. Supports speech-to-text dictation input. Conditionally required based on organization-specific activity type configuration. Max 5000 characters. | - |
status |
enum |
Lifecycle state of the activity record. Drives coordinator approval queue visibility, Bufdir reporting eligibility, and UI state presentation. State machine transitions are enforced server-side. | required |
is_proxy_registration |
boolean |
True when the activity was registered by a coordinator or admin on behalf of the target peer mentor via proxy reporting. Enables coordinator audit filtering and delegation grant linkage. | required |
registered_by_user_id |
uuid |
FK to users. Populated only when is_proxy_registration is true. Identifies the coordinator or admin who submitted the registration. Combined with delegation_grants for full Bufdir audit trail. | - |
bulk_registration_id |
uuid |
FK to bulk_registrations. Populated when this activity record was spawned as part of a coordinator bulk registration batch. Enables tracing back to the original batch operation. | - |
is_draft |
boolean |
Indicates the activity is a partial wizard save that has not been submitted. Draft records are excluded from all reporting, duplicate detection, and coordinator queues. Cleaned up after 30 days. | required |
draft_data |
json |
Serialized BLoC wizard state for interrupted registrations. Populated only when is_draft is true. Restored on wizard re-entry to allow seamless continuation. Cleared on final submission. | - |
location |
string |
Optional freetext description of where the activity took place (e.g., 'Home visit – Oslo', 'Phone call'). Not used for geographic matching but provides context for coordinator review. | - |
has_documents |
boolean |
Denormalized flag indicating whether one or more activity_documents records are linked. Enables fast list rendering without a join. Updated by Document Storage Service on attach/detach. | required |
document_count |
integer |
Denormalized count of linked activity_documents. Max 5 per NHF Bufdir evidence rules. Enforced by Document Storage Service before accepting new uploads. | required |
rejection_reason |
text |
Coordinator-supplied reason when status transitions to 'rejected'. Mandatory on rejection. Displayed to peer mentor on the Activity Summary Screen for correction guidance. | - |
coordinator_note |
text |
Optional note added by a coordinator during approval or correction review. Not visible to peer mentors unless organization configuration enables transparency mode. | - |
created_at |
datetime |
Server-generated UTC timestamp of record creation. Immutable after insert. Used for audit trails, personal statistics, and coordinator dashboard filtering. | required |
updated_at |
datetime |
Server-updated UTC timestamp on every modification. Maintained via Supabase database trigger. Used for cache invalidation in Statistics Repository and change detection. | required |
deleted_at |
datetime |
Soft delete timestamp. When populated the record is excluded from all queries via RLS policy. Retained permanently for Bufdir audit trail integrity. Physical deletion is not permitted. | - |
Database Indexes
idx_activities_user_id
Columns: user_id
idx_activities_organization_id
Columns: organization_id
idx_activities_activity_date
Columns: activity_date
idx_activities_activity_type_id
Columns: activity_type_id
idx_activities_contact_id
Columns: contact_id
idx_activities_status
Columns: status
idx_activities_bulk_registration_id
Columns: bulk_registration_id
idx_activities_deleted_at
Columns: deleted_at
idx_activities_user_date_type
Columns: user_id, activity_date, activity_type_id
idx_activities_org_date_status
Columns: organization_id, activity_date, status
idx_activities_org_user_date
Columns: organization_id, user_id, activity_date
idx_activities_is_draft
Columns: is_draft
Validation Rules
required_core_fields
error
Validation failed
duration_positive_integer
error
Validation failed
activity_date_not_future
error
Validation failed
activity_date_within_configurable_window
error
Validation failed
summary_required_for_qualifying_activity_types
error
Validation failed
contact_required_for_individual_activity_types
error
Validation failed
summary_max_length
error
Validation failed
rejection_reason_required_on_rejection
error
Validation failed
registered_by_required_when_proxy
error
Validation failed
draft_cleanup_after_30_days
info
Validation failed
Business Rules
organization_rls_enforcement
Every activity must be scoped to the authenticated user's active organization. Supabase RLS policies use auth.uid() and a custom JWT org_id claim to prevent cross-organization data reads and writes. Peer mentors can only read their own activities; coordinators can read all activities within their org scope.
duplicate_activity_detection
Before a new activity is submitted (status transitions from draft to submitted), the system checks for existing activities with the same user_id, activity_date (±15 min window), activity_type_id, and contact_id. A confidence score is computed and if above threshold the Duplicate Warning Dialog is shown to allow the peer mentor to confirm or cancel the submission.
cross_org_duplicate_prevention
For users who are members of multiple organizations (NHF use case), the Duplicate Report Prevention Service scans activities across all affiliated organizations to detect double-reporting of the same event under different org contexts. Applies fuzzy matching on activity_type, contact_id, activity_date, and duration_minutes.
status_state_machine
Activity status must follow valid transitions: draft→submitted, submitted→pending_review, pending_review→approved|rejected, rejected→submitted (after correction), approved→corrected (coordinator correction). Reverse transitions and skipping states are rejected. Transitions are executed via authenticated Supabase RPCs to prevent client-side manipulation.
proxy_registration_authorization
When is_proxy_registration is true, the submitting user (registered_by_user_id) must hold the coordinator or admin role within the same organization as the target peer mentor. The Activity Delegation Service validates this before writing the activity and creates a corresponding delegation_grants audit record.
activity_type_org_scope
The activity_type_id must reference an activity_types record belonging to the same organization_id as the activity. Prevents cross-organization activity type misuse and ensures Bufdir reporting categorization is org-specific.
contact_org_scope
When contact_id is provided, the referenced contact must belong to the same organization as the activity. Enforced via Supabase FK constraint and application-level validation in Activity Validation Service.
bufdir_reporting_eligibility
Only activities with status='approved' (or 'submitted' for organizations without a coordinator approval workflow) are included in Bufdir report aggregations. Draft and rejected activities are always excluded. This ensures grant reporting reflects only verified peer mentor contributions.
soft_delete_only
Activities may never be physically deleted from the database. Deletion sets deleted_at to the current timestamp and excludes the record from all RLS-filtered queries. This preserves the immutable Bufdir audit trail and ensures coordinator correction history remains intact.
document_count_limit
An activity may have at most 5 attached documents, as required by NHF Bufdir evidence rules. The Document Storage Service checks document_count before accepting a new upload and rejects the operation with a user-facing error if the limit is reached.
immutable_audit_log_on_change
Every state change to an activity record (field edits, status transitions, coordinator corrections) must trigger creation of an immutable activity_logs entry capturing the actor, timestamp, changed fields, and old/new values. This is enforced by a Supabase database trigger and cannot be bypassed by application code.
CRUD Operations
Storage Configuration
Entity Relationships
Activities may have up to 5 supporting document attachments for Bufdir audit evidence
Every modification to an activity creates an immutable audit log entry
Each activity is categorized by a single organization-specific activity type
An activity is typically linked to the specific contact who received peer mentor support
Activities are scoped to an organization for RLS enforcement and Bufdir attribution
A bulk registration spawns individual activity records for each selected peer mentor
Each delegation grant references the specific activity that was registered by proxy
A user registers multiple activity records over their lifecycle as a peer mentor