circle-exclamation
KatanOS will not receive any updates at the moment, which is why I decided to make it open source.

databaseDatabase

KatanOS is local-first. There is no server database.

Persistence is split into:

  • services/storage.ts (raw key/value storage adapter)

  • services/db.ts (typed domain API)

Storage Layer (services/storage.ts)

Configuration:

  • IndexedDB database: katanos_storage

  • object store: kv

  • migration flag: katanos_idb_migrated_v1

Behavior:

  • loads all key/value pairs into in-memory cache on init

  • migrates known keys from localStorage to IndexedDB once

  • falls back to localStorage when IndexedDB is unavailable

Public API:

  • initStorage(migrateKeys)

  • storageGetRaw(key)

  • storageSetRaw(key, value)

  • storageRemoveRaw(key)

  • getStorageStatus()

Domain Layer (services/db.ts)

db namespaces:

  • auth

  • events

  • todos

  • checklists

  • transactions

  • financeBudgets

  • financeGoals

  • financeDebts

  • financeRecurring

  • contacts

  • habits

  • journal

  • books

  • vault

  • autosave

  • createUserBackupPayload

  • restore

Canonical Data Keys

Data Schema Reference

The table below is the practical schema index for persistence and restore operations.

Storage Key
Entity Type
Scope
Ownership Model
Notes

chronos_users

User[]

global

user record by id

includes profile/settings/security fields

chronos_current_user

User (single)

runtime-global

active user snapshot

not an array

chronos_events

CalendarEvent[]

shared collection

per-item userId

agenda module

chronos_todos

TodoItem[]

shared collection

per-item userId

sticky todos

chronos_checklists

Checklist[]

shared collection

per-item userId

todo sub-domain

chronos_transactions

Transaction[]

shared collection

per-item userId

finance ledger

chronos_finance_budgets

FinanceBudget[]

shared collection

per-item userId

finance planning

chronos_finance_goals

FinanceGoal[]

shared collection

per-item userId

savings goals

chronos_finance_debts

FinanceDebt[]

shared collection

per-item userId

debt tracker

chronos_finance_recurring

FinanceRecurring[]

shared collection

per-item userId

recurring entries

chronos_contacts

Contact[]

shared collection

per-item userId

contacts module

chronos_habits

Habit[]

shared collection

per-item userId

habits module

chronos_journal

JournalEntry[]

shared collection

per-item userId

journal module

chronos_books

Book[]

shared collection

per-item userId

bookshelf module

chronos_vault

EncryptedVault[]

shared collection

per-item userId

encrypted blobs, special handling in delete/restore

Schema invariants used across modules:

  • all domain entities except User and chronos_current_user are persisted as arrays

  • per-user separation is done by filtering item.userId

  • IDs are generated as UUIDs for new records

  • timestamps are stored as ISO strings

Data Contracts

Primary interfaces are defined in types.ts.

Major entities:

  • User

  • CalendarEvent

  • TodoItem

  • Checklist

  • Transaction

  • FinanceBudget

  • FinanceGoal

  • FinanceDebt

  • FinanceRecurring

  • Contact

  • Habit

  • JournalEntry

  • Book

  • EncryptedVault

User Isolation Model

Most collections are shared arrays keyed by userId and filtered on read.

Pattern used in list methods:

Authentication and Account Data

Auth behavior (db.auth):

  • case-insensitive username matching

  • login/register/update settings

  • password reset via security question/answer

  • lock-PIN verification

Hashing parameters in db.ts:

  • scheme: PBKDF2-SHA256

  • iterations: 150000

  • salt bytes: 16

  • hash bytes: 32

  • stored format: pbkdf2$<iterations>$<saltBase64>$<hashBase64>

Compatibility fallback:

  • if Web Crypto is unavailable, secrets may be stored in plain text (documented limitation)

Vault Persistence Behavior

db.vault stores encrypted vault blobs (EncryptedVault) per user id.

Special handling:

  • legacy vault entries without userId are migrated to current user on read

  • db.auth.deleteUserData currently removes the entire vault key (chronos_vault), not only one user slice

Backup Payloads (db.ts)

db can build backup payloads with:

  • scope: 'all' via internal buildBackupPayload

  • scope: 'user' via createUserBackupPayload(userId)

Payload structure includes:

  • version

  • timestamp

  • userId

  • currentUser

  • scope

  • data collections

  • extras

    • weather location keys

    • cloud backup keys

    • app localStorage keys

Backup payload shape (effective contract):

Contributor note:

  • when adding a new persistent domain, update DATA_KEYS, backup build/filter logic, and restore branches together

  • if restore rules differ between scope: 'user' and scope: 'all', document both explicitly

Restore Semantics (db.restore)

User-scope restore (scope: 'user')

  • merges imported records for target user

  • keeps records for other users

  • may overwrite vault with incoming data.vault

  • can restore currentUser and extras

Full-scope restore (non-user scope)

  • replaces most collection keys directly when present

  • restores extras

Important implementation detail:

  • full-scope branch does not currently write chronos_vault explicitly

Autosave and Electron Snapshot Notes

db.set(...) triggers autosave via window.katanos.saveSnapshot(...) when Electron bridge is available.

Electron main process serializes autosave/export folder data using USER_DATA_FILES:

  • events

  • todos

  • transactions

  • contacts

  • habits

  • journal

So Electron-side autosave/export-folder artifacts currently do not include all db domains (for example checklists, finance planning entities, books, vault).

Auxiliary LocalStorage Keys (non-canonical)

Examples used by modules/components:

  • katanos_weather_loc_<userId>

  • katanos_emoji_recent

  • katanos_last_login_lang

  • katanos_last_login_theme

  • katanos_login_bg

  • katanos_pomodoro_<userId>

  • katanos.readingGoal.<userId>

  • chronos_notified_events (sessionStorage)

Failure and Quota Behavior

On quota errors, db.ts dispatches katanos:notify storage warnings.

Storage write/read failures are generally caught with console warnings/errors to keep UI running.

Last updated

Was this helpful?