core PK: id 9 required 1 unique

Description

A freeform text note authored by a peer mentor or coordinator, optionally linked to a contact. Supports draft auto-save and offline-first mutation via Drift. Scoped to a single organization; soft-deleted only.

14
Attributes
5
Indexes
6
Validation Rules
15
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Surrogate primary key, generated client-side for offline-first compatibility
PKrequiredunique
organization_id uuid Tenant scope. Every query must filter by this column. References organizations table.
required
user_id uuid The peer mentor or coordinator who authored the note. References users table.
required
contact_id uuid Optional link to the contact this note concerns. Null for standalone/general notes.
-
title string Short optional heading for the note. Max 200 characters.
-
body text Main note content, plain text or light markdown. Required when note is finalized.
required
draft_body text Auto-saved draft content before the user explicitly saves. Managed by draft-auto-save-handler. Null once finalized.
-
is_draft boolean True while the note has unsaved draft content and has not been explicitly published.
required
is_pinned boolean Whether the note is pinned to the top of the notes list for quick access.
required
is_deleted boolean Soft-delete flag. Deleted notes are excluded from all listings but retained for audit.
required
deleted_at datetime Timestamp when the note was soft-deleted. Null if active.
-
deleted_by_user_id uuid User who performed the soft delete. Required when is_deleted is true.
-
created_at datetime UTC timestamp when the note was first saved.
required
updated_at datetime UTC timestamp of the last substantive edit to body or title.
required

Database Indexes

idx_notes_org_user
btree

Columns: organization_id, user_id

idx_notes_contact
btree

Columns: contact_id

idx_notes_org_created
btree

Columns: organization_id, created_at

idx_notes_user_active
btree

Columns: user_id, is_deleted

idx_notes_pinned
btree

Columns: user_id, is_pinned, is_deleted

Validation Rules

body_not_empty error

Validation failed

title_max_length error

Validation failed

deleted_at_consistency error

Validation failed

contact_exists error

Validation failed

user_active error

Validation failed

updated_at_monotonic error

Validation failed

Business Rules

org_scope_isolation
always

Every read and write query must include organization_id matching the authenticated user's active org context. Cross-org note access is forbidden regardless of user role.

soft_delete_only
on_delete

Notes must never be hard-deleted. is_deleted=true with deleted_at and deleted_by_user_id set is the only permitted removal path, preserving audit trail for Bufdir.

Enforced by: Note Service
author_or_coordinator_edit
on_update

Only the original author (user_id) or a coordinator within the same organization may edit or delete a note. Peer mentors cannot edit other peer mentors' notes.

draft_promotion
on_update

When a note is saved explicitly, draft_body is copied to body and draft_body is cleared. is_draft is set to false. The transition is atomic.

contact_org_match
on_create

If contact_id is provided, the referenced contact must belong to the same organization_id as the note. Cross-org contact linking is rejected.

Enforced by: Note Service
offline_optimistic_mutation
always

Note creates and updates are written to the Drift local store immediately and queued in mutation-outbox-service. On sync, server conflicts are resolved by last-write-wins on updated_at.

pin_limit
on_update

A user may have at most 10 pinned notes per organization. Attempting to pin beyond the limit produces a warning and is rejected.

Enforced by: Note Service

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage