rnotes-online/MODULE_SPEC.md

5.8 KiB

rNotes — Collaborative Notebooks

Module ID: rnotes Domain: rnotes.online Version: 0.1.0 Framework: Next.js 14 / React 18 / Prisma / PostgreSQL / TipTap Status: Active

Purpose

Rich note-taking with notebooks, tags, file uploads, voice transcription, and canvas integration. Supports per-notebook collaboration with role-based access. Notes can embed as shapes on the rSpace canvas.

Data Model

Core Entities (Prisma)

Model Key Fields Relationships
User id, did (EncryptID DID), username has many Notebook, Note, NotebookCollaborator
Notebook id, title, slug (unique), description, coverColor, isPublic, canvasSlug, canvasShapeId has many Note, NotebookCollaborator, SharedAccess
NotebookCollaborator userId, notebookId, role (OWNER/EDITOR/VIEWER) belongs to User, Notebook
Note id, title, content, contentPlain, type (enum), url, isPinned, sortOrder, canvasSlug, canvasShapeId belongs to Notebook, User (author)
Tag id, name (unique), color many-to-many with Note via NoteTag
SharedAccess notebookId, sharedByUserId, sharedWithDID, role cross-user sharing

Note Types

NOTE, CLIP, BOOKMARK, CODE, IMAGE, FILE, AUDIO

Collaborator Roles

OWNER, EDITOR, VIEWER (per-notebook)

Permission Model

Space Integration

rNotes currently operates at the notebook level, not the space level. The migration path adds a space-level role that sets the default notebook access.

  • SpaceVisibility: Mapped to notebook isPublic flag (public → true)
  • Default role for open spaces: PARTICIPANT (can create notebooks and edit own notes)

Capabilities

Capability Required SpaceRole AuthLevel Description
view_notebooks VIEWER BASIC See notebook list and read notes
create_notebook PARTICIPANT STANDARD Create new notebooks
edit_own_notes PARTICIPANT STANDARD Edit/delete own notes in any shared notebook
edit_any_notes MODERATOR STANDARD Edit/delete any user's notes
manage_notebooks ADMIN ELEVATED Delete notebooks, manage collaborators

Module-Specific Overrides

Per-notebook CollaboratorRole overrides the space-level default:

  • Space PARTICIPANT + Notebook OWNER → full notebook control
  • Space PARTICIPANT + Notebook VIEWER → read-only on that notebook
  • Space MODERATOR → EDITOR on all notebooks (override)
  • Space ADMIN → OWNER on all notebooks (override)

Current Auth Implementation

  • EncryptID DID from JWT claims
  • getAuthUser(request) → extracts DID, upserts User
  • requireAuth(request) → returns 401 if no valid token
  • getNotebookRole(userId, notebookId) → looks up CollaboratorRole
  • First authenticated user auto-claims orphaned notebooks

API Endpoints

Method Path Auth Required Capability Description
GET /api/notebooks Yes view_notebooks List user's notebooks
POST /api/notebooks Yes create_notebook Create notebook
GET /api/notebooks/[id] Depends view_notebooks Get notebook details
PUT /api/notebooks/[id] Yes edit_own_notes Update notebook
DELETE /api/notebooks/[id] Yes manage_notebooks Delete notebook
GET /api/notebooks/[id]/notes Depends view_notebooks List notes
GET /api/notebooks/[id]/canvas Yes view_notebooks Get canvas shape data
PUT /api/notebooks/[id]/canvas Yes edit_own_notes Update canvas binding
GET /api/notes Yes view_notebooks Global notes list
POST /api/notes Yes edit_own_notes Create note
GET /api/notes/[id] Depends view_notebooks Get note
PUT /api/notes/[id] Yes edit_own_notes Update note
DELETE /api/notes/[id] Yes edit_own_notes Delete own note
GET /api/notes/search Yes view_notebooks Full-text search
POST /api/uploads Yes edit_own_notes Upload file
GET /api/uploads/[filename] Depends view_notebooks Download file
POST /api/voice/transcribe Yes edit_own_notes Audio→text
POST /api/voice/diarize Yes edit_own_notes Speaker diarization

Canvas Integration

Notes and notebooks embed as shapes on the rSpace canvas:

  • folk-note: Individual note card (title + content preview)
  • folk-notebook: Notebook container showing note count
  • Bidirectional binding via canvasSlug and canvasShapeId fields
  • Editing a note shape on canvas updates the note in PostgreSQL
  • Creating a note in rNotes can auto-place a shape on canvas

Cross-Module Dependencies

Module Integration
rSpace Canvas shape embedding (folk-note, folk-notebook)
EncryptID DID-based identity and authentication
rFiles File attachments referenced in notes

Local-First / Offline Support

  • Currently server-authoritative (Prisma/PostgreSQL)
  • Client state managed with Zustand
  • Local-first Transformers.js for on-device AI inference
  • Future: TipTap Y.js integration for offline collaborative editing
  • Future: IndexedDB cache for offline note access

Migration Plan

  1. Add space concept: link notebooks to a space slug (optional, backwards-compatible)
  2. Import SpaceRole from SDK for space-level role resolution
  3. Add resolveSpaceRole() call in getAuthUser() or a new middleware layer
  4. Cascade space role → default notebook role:
    • Space PARTICIPANT → Notebook EDITOR (on newly accessed notebooks)
    • Space VIEWER → Notebook VIEWER
    • Space MODERATOR → Notebook EDITOR (all notebooks)
    • Space ADMIN → Notebook OWNER (all notebooks)
  5. Keep per-notebook CollaboratorRole overrides for fine-grained control
  6. Replace direct role checks with hasCapability() in API route handlers