# LoreLoom Auth And Users

## Purpose

This document proposes a lightweight user account and permissions model for LoreLoom.

It is a planning document only. It does not imply that auth should be implemented immediately.

The goal is to add enough account structure for self-hosted personal and household use without pulling LoreLoom toward cloud-SaaS complexity.

## Design Priorities

Any user system for LoreLoom should preserve the existing product values:

- simple enough to run on a Raspberry Pi
- understandable to maintain
- local-first in spirit, even with backend persistence
- writer-owned data
- no vendor identity dependency
- no public-SaaS assumptions

## Scope

This document covers:

- single-user instances
- small multi-user household instances
- local password-based accounts
- project ownership
- a path toward future project sharing
- per-user diagnostics consent
- migration from today’s no-auth mode

This document does not propose:

- OAuth
- Google, Apple, or Microsoft login
- public multi-tenant SaaS
- live collaboration
- role hierarchies for teams or organizations

## Deployment Modes

### Single-User Instance

This should remain the default and simplest LoreLoom deployment.

Typical use:

- one person
- one browser or a few personal devices
- home LAN or localhost
- self-hosted on a Raspberry Pi, mini PC, or laptop

Behavior goals:

- one initial local account
- minimal setup friction
- clear ownership of all projects
- backups remain straightforward

For a single-user instance, LoreLoom should feel closer to a personal writing appliance than a multi-user web app.

### Multi-User Household Instance

This is the highest-priority multi-user case worth designing for early.

Typical use:

- a family or shared household server
- two to five users
- each person has their own login
- each person owns their own projects by default

Behavior goals:

- simple account creation by the instance owner or installer
- no accidental cross-user access
- shared machine friendly
- still light enough for Raspberry Pi hosting

This is not full collaboration. It is closer to a shared household installation with separate private workspaces.

## Recommended Account Model

### Local Account System

LoreLoom should use a local account system stored in SQLite.

Each account should have:

- stable user ID
- username
- display name
- password hash
- account status
- created/updated timestamps
- optional last login timestamp
- optional diagnostics opt-in flag

Why local accounts fit LoreLoom:

- no external identity dependency
- works on LAN-only deployments
- understandable backup and restore model
- consistent with self-hostable goals

### Password-Based Login

The first account system should be username plus password.

Recommended behavior:

- local login form
- secure password hashing
- server-side session cookie
- logout support
- optional session expiry
- local account passwords should have a minimum length of 6 characters

Recommended implementation shape later:

- password hashing with Node's built-in `scrypt` for the initial self-hosted implementation
- consider `argon2id` later only if the extra dependency and build surface is justified
- secure HTTP-only session cookie
- CSRF protection once authenticated mutations exist

For LoreLoom’s priorities, the simpler rule is:

- prefer the least surprising secure local login flow
- avoid custom crypto primitives
- avoid token-heavy SPA auth complexity if cookie sessions can stay simple

## Ownership And Permissions

### Project Ownership

Every project should belong to exactly one user.

Server-side records should use explicit ownership:

- `projects.owner_user_id`

During migration from pre-auth databases, `projects.owner_user_id` may remain `NULL` temporarily:

- existing projects can stay unowned until first-run admin setup completes
- first-run admin setup assigns those unowned projects to the first admin
- normal authenticated use should converge to every project having an owner

That ownership should imply access to the full project graph:

- structure nodes
- text blocks
- codex entries
- revision snapshots

The simplest permission rule for v1 auth:

- owners can read, write, export, delete, and back up their own projects
- non-owners cannot access those projects

For local multi-user testing, account creation should remain admin-driven:

- no public signup
- admins can create local `user` and `admin` accounts
- admins can reset passwords by generating a temporary password and sharing it manually
- no email recovery in the first implementation
- users should be able to change their own password after login
- temporary passwords should be visible in the admin UI and should support clipboard fallback on LAN HTTP
- older authenticated databases may still contain legacy `member` role values during migration, but they should be normalized safely to `user`

This is easy to reason about and fits the single-user plus household model well.

### Future Project Sharing

Project sharing should be planned for, but not implemented immediately.

A reasonable future shape:

- explicit per-project shares
- invited local users only
- simple roles such as:
  - `viewer`
  - `editor`

For now, sharing should remain a non-goal for the first auth release because it increases complexity in:

- API authorization checks
- UI expectations
- conflict behavior
- diagnostics privacy
- backup semantics

The data model should leave room for future sharing, but the first account system should assume private ownership only.

## Diagnostics Opt-In Per User

Diagnostics participation should be controlled per user, not globally by assumption.

Recommended model:

- each user has a `diagnostics_opt_in` boolean
- default to `false`
- the diagnostics page explains what diagnostic bundles include and exclude
- export remains manual even when opt-in is enabled

Why per-user opt-in matters:

- different users on the same household instance may have different comfort levels
- it keeps consent closer to the person whose environment is being reported
- it supports writer ownership and trust

Important distinction:

- opt-in should control whether LoreLoom records richer local diagnostic history for that user
- it should not block a minimal manual diagnostic export that only contains environment and health information needed for basic troubleshooting

## Migration From Current No-Auth Mode

Today LoreLoom effectively runs in a no-auth mode with one implicit writer context.

The migration path should be explicit and conservative.

### Recommended Migration Strategy

On first startup after auth is introduced:

1. detect whether the database has existing projects but no users
2. enter a one-time setup flow
3. prompt for creation of the first local account
4. assign existing projects to that first account
5. mark the instance as initialized

This preserves the current single-user reality without pretending there was already user separation.

### Transitional Instance State

It may be useful to introduce a small instance-level state such as:

- `auth_mode = disabled | setup_required | enabled`

Suggested behavior:

- `disabled`
  - legacy/no-auth behavior during development or controlled transition
- `setup_required`
  - existing data found, but first account not created yet
- `enabled`
  - normal login flow required

This gives a safer path than forcing immediate login behavior onto existing installs.

### Frontend Migration Considerations

The browser currently assumes one local workspace.

When auth arrives, the frontend should avoid silently mixing data between users.

Recommended behavior:

- local cache becomes user-scoped after login
- no-auth local data should be migrated into the first authenticated user context during setup
- logging out should not expose another user’s cached project state

## SQLite Schema Changes

The current schema centers on projects and the project graph. Auth adds instance and user ownership tables.

### New Tables

#### `instance_settings`

Purpose:

- store small instance-wide configuration and setup state

Suggested fields:

- `id` `INTEGER PRIMARY KEY CHECK (id = 1)`
- `auth_mode` `TEXT NOT NULL`
- `instance_name` `TEXT NULL`
- `created_at` `TEXT NOT NULL`
- `updated_at` `TEXT NOT NULL`

#### `users`

Purpose:

- local user accounts

Suggested fields:

- `id` `TEXT PRIMARY KEY`
- `username` `TEXT NOT NULL UNIQUE`
- `display_name` `TEXT NOT NULL`
- `password_hash` `TEXT NOT NULL`
- `status` `TEXT NOT NULL`
- `diagnostics_opt_in` `INTEGER NOT NULL DEFAULT 0`
- `created_at` `TEXT NOT NULL`
- `updated_at` `TEXT NOT NULL`
- `last_login_at` `TEXT NULL`

Suggested indexes:

- `INDEX users_username_idx ON users(username)`

#### `sessions`

Purpose:

- track active local login sessions

Suggested fields:

- `id` `TEXT PRIMARY KEY`
- `user_id` `TEXT NOT NULL`
- `created_at` `TEXT NOT NULL`
- `updated_at` `TEXT NOT NULL`
- `expires_at` `TEXT NOT NULL`
- `last_seen_at` `TEXT NULL`
- `user_agent` `TEXT NULL`
- `ip_address` `TEXT NULL`

Foreign key:

- `user_id REFERENCES users(id) ON DELETE CASCADE`

Suggested indexes:

- `INDEX sessions_user_id_idx ON sessions(user_id)`
- `INDEX sessions_expires_at_idx ON sessions(expires_at)`

### Changes To Existing Tables

#### `projects`

Add:

- `owner_user_id` `TEXT NOT NULL`

Foreign key:

- `owner_user_id REFERENCES users(id) ON DELETE RESTRICT`

Suggested index:

- `INDEX projects_owner_user_id_idx ON projects(owner_user_id)`

Rationale:

- projects should not be orphaned if a user is deleted casually
- account deletion should likely require explicit project transfer or deletion later

### Sharing Tables For Later, Not Now

Do not add project-sharing tables in the first auth migration unless implementation is imminent.

If documented for future use, they might look like:

- `project_shares`

But leaving them out initially keeps the schema smaller and the operational model clearer.

## API Changes

The current API assumes one durable project space. Auth changes that assumption.

### New Auth Endpoints

Likely first-pass routes:

- `POST /api/auth/setup`
- `POST /api/auth/login`
- `POST /api/auth/logout`
- `GET /api/auth/session`

Purpose:

- initialize the first account
- create a local session
- end a session
- allow the frontend to hydrate the current logged-in user

### Changes To Existing Project Routes

Existing project routes should become user-scoped by session, not by explicit user ID in the path.

Examples:

- `GET /api/projects`
  - returns only the current user’s project summaries
- `GET /api/projects/:id/bundle`
  - allowed only for the owner
- `PUT /api/projects/:id/bundle`
  - allowed only for the owner
- `DELETE /api/projects/:id`
  - allowed only for the owner

This keeps the API simpler and avoids exposing unnecessary user identifiers in frontend routing.

### Diagnostics API Changes

Diagnostics endpoints should respect both:

- login state
- user diagnostics preferences

Recommended behavior:

- minimal health/config diagnostics can still exist for local troubleshooting
- richer per-user diagnostic history should only be available within that user’s authenticated session

## Frontend UX Changes

The frontend should remain calm and practical.

### Login And Setup

New flows likely needed:

- first-run setup screen when auth is required but not initialized
- login screen
- logout control
- session-expired state

These should be intentionally small and boring.

### User Context

Once logged in, the UI should show a light indication of who is signed in.

Examples:

- username in the app shell
- small account menu with logout
- diagnostics preference toggle in settings or diagnostics page

### Project UX

Project creation should remain simple, but projects now belong to the current user automatically.

Future sharing should not affect the initial UX yet.

### Local Cache UX

Since LoreLoom is local-first, auth introduces a subtle but important UX responsibility:

- keep local caches separated per user
- avoid showing one user another user’s locally cached project data after logout/login

This matters more than fancy account UI.

## Backup And Export Implications

Auth changes backup semantics, but backups should remain writer-owned and portable.

### Project Backup Export

Project backups should remain project-centric, not account-centric.

Recommended behavior:

- project JSON backup includes the project graph
- it does not need to include password hashes or session data
- it may include ownership metadata only as informational import context

When importing into another instance:

- imported projects should usually become owned by the currently logged-in user
- original owner metadata should not automatically recreate unknown users

This keeps project backups portable.

### Story TXT Export

No meaningful auth change is needed here.

TXT export should remain a content export owned by the current project owner.

### Diagnostic Bundle Export

Diagnostic bundles should continue to exclude manuscript and codex content.

With auth:

- export should reflect the current authenticated user context
- per-user diagnostic history should only include that user’s diagnostics data where relevant

### Instance Backups

Server operators will still need host-level SQLite backups.

With auth enabled, SQLite backups now include:

- user accounts
- sessions
- project ownership metadata
- project data

This increases sensitivity of the database backup, so backup handling guidance should become more explicit.

## Risks

Introducing auth changes the product in meaningful ways.

Main risks:

- increased complexity in a product that values simplicity
- accidental data exposure between household users if local cache scoping is wrong
- support burden around password resets on self-hosted instances
- more sensitive SQLite backups because user account data now exists
- session bugs that make offline-first behavior feel fragile

For LoreLoom, the biggest practical risk is not “weak enterprise auth.” It is losing the product’s calm, understandable model.

## Non-Goals

For the first auth and users release, explicitly avoid:

- OAuth and third-party identity providers
- public signup flows
- email verification
- password reset by email
- organization/team management
- collaboration permissions
- real-time shared editing
- fine-grained per-node or per-text-block permissions
- public sharing links

Those features may be valid later, but they would pull LoreLoom toward a very different system.

## Recommended Rollout Order

If auth is implemented later, a practical rollout order would be:

1. add user, session, and project ownership schema
2. add first-run setup and first local account creation
3. add login/logout/session endpoints
4. scope project APIs to the authenticated owner
5. scope frontend local cache to the signed-in user
6. add per-user diagnostics opt-in
7. only later evaluate project sharing

## Summary

The right first auth model for LoreLoom is not “internet app auth.”

It is:

- local accounts
- password login
- session cookies
- private project ownership
- conservative migration from today’s no-auth mode
- room for future sharing without implementing it yet

That gives LoreLoom a path from personal writer tool to small household instance without giving up simplicity, Raspberry Pi friendliness, or writer ownership.
