Note
Data Entity
Description
A free-text or structured note created by a peer mentor or coordinator, optionally linked to a contact. Notes capture follow-up observations, home visit summaries, personal reminders, and assignment-related context. Autosaved drafts are supported to prevent data loss on mobile.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key — unique note identifier | PKrequiredunique |
user_id |
uuid |
FK to users — the peer mentor or coordinator who authored the note | required |
organization_id |
uuid |
FK to organizations — enforces tenant isolation so notes are never cross-visible between organizations | required |
contact_id |
uuid |
FK to contacts — the contact this note is about. Nullable for general notes not tied to a specific contact. | - |
title |
string |
Optional short title or subject line for the note. Max 255 characters. | - |
content |
text |
Main body of the note. Supports plain text; entered via keyboard or speech-to-text. Required on publish, nullable while in draft. | - |
note_type |
enum |
Categorises the note's purpose to allow filtering and structured display in the notes list | required |
status |
enum |
Lifecycle state of the note. Drafts are autosaved locally and server-side but not shown in the primary list view until published. | required |
is_pinned |
boolean |
Whether the note is pinned to the top of the notes list for this user | required |
is_private |
boolean |
If true, only the author can read this note. If false, coordinators with access to the linked contact may also read it. | required |
structured_data |
json |
Optional JSON blob for structured home visit report fields (Blindeforbundet): health_status, course_interest, assistive_device_situation, way_forward. Null for general notes. | - |
autosave_version |
integer |
Incremented monotonically on each autosave. Used by the client to detect stale local drafts and resolve last-write-wins conflicts. | required |
created_at |
datetime |
UTC timestamp when the note record was first created (including initial draft save) | required |
updated_at |
datetime |
UTC timestamp of the most recent update, including autosaves | required |
published_at |
datetime |
UTC timestamp when status transitioned from draft to published. Null for drafts. | - |
deleted_at |
datetime |
Soft-delete timestamp. Null means the record is active. Non-null means logically deleted and excluded from all standard queries. | - |
Database Indexes
idx_notes_user_id
Columns: user_id
idx_notes_contact_id
Columns: contact_id
idx_notes_organization_id
Columns: organization_id
idx_notes_user_status
Columns: user_id, status
idx_notes_contact_status
Columns: contact_id, status
idx_notes_updated_at
Columns: user_id, updated_at
idx_notes_deleted_at
Columns: deleted_at
idx_notes_fts
Columns: title, content
Validation Rules
title_max_length
error
Validation failed
content_required_on_publish
error
Validation failed
note_type_valid_enum
error
Validation failed
structured_data_schema
warning
Validation failed
contact_id_valid_uuid
error
Validation failed
user_id_required
error
Validation failed
offline_content_size_limit
error
Validation failed
Business Rules
tenant_isolation
A note's organization_id must match the authenticated user's active organization context. Cross-organization note reads or writes are rejected at the API layer.
author_ownership
Only the note's author (user_id) may update or delete the note. Coordinators may read non-private notes belonging to contacts they manage, but cannot modify them.
private_note_visibility
When is_private is true, the note is visible only to the author regardless of role. When is_private is false, coordinators with read access to the linked contact may also read the note.
publish_requires_content
A note may only transition to status=published if the content field is non-empty and non-whitespace. Drafts with empty content remain in draft indefinitely.
soft_delete_only
Notes are never hard-deleted from the database. Deletion sets deleted_at to the current timestamp. All queries filter WHERE deleted_at IS NULL by default.
autosave_version_monotonic
autosave_version must only ever increase. The server rejects updates with a version equal to or lower than the persisted value to prevent stale autosaves from overwriting newer content.
contact_belongs_to_same_org
When contact_id is provided, the referenced contact must belong to the same organization as the note author. Cross-org contact linking is rejected.
published_at_immutable
Once published_at is set it cannot be changed. Re-publishing an already-published note is a no-op for this field.