The database
Everything NoCloudMe knows lives in one unified SQLite database — your finances, your photos' metadata, your family tree, your house, your health. One file, on hardware you own, queryable with any SQLite tool. See Architecture for where it sits, and Open standards for the formats each domain normalises to.
This page is generated
The tables below are read from the live database schema every time this manual is built — so it can't drift from reality. Only the per-table purpose is hand-written.
How to read it
Domain prefix. Every table starts with its domain: app_, fin_, people_, home_, photo_,
health_, tax_, chat_, inv_. That's the first thing to look at — it tells you which part of
your life the table belongs to.
Fundamental vs derived. A column prefixed calc_ is derived: it's computed from other data
and regenerated by the builders, so it is never hand-edited and never authoritative. Everything else
is fundamental — the real, entered-once data. If a calc_ value looks wrong, the fix is upstream,
in whatever produces it.
Conventions. is_* are booleans · <entity>_id are foreign keys · sort_order is ordering
(never order, a reserved word) · identifiers are English, snake_case. The full convention lives in
docs/DB_NAMING.md.
Nothing here is your data. This page lists structure only — table and column names, types and purpose. No row ever leaves your machine; see Security & privacy.
Safety net
Every write to this database goes through a snapshot-first, append-only ledger (dbsafe): the
previous state is copied before the change and the operation is recorded, so any accident can be
rolled back. Bulk operations on the archive are reversible too — see Concepts.
| Table | Purpose |
|---|---|
| APP (product: users, sections, languages) | |
app_languages |
DIMENSION of the UI languages on offer (code is the BCP-47 tag). The UI is written in English and translated from it. |
app_sections |
CATALOG of everything installable on the Home: the built-in sections plus every App Store app (is_app). One row per section, with the URL it opens and the emoji/description shown on its tile. |
app_timezones |
DIMENSION of selectable timezones (IANA names). What turns a stored UTC timestamp into the hour you actually read. |
app_user_sections |
Which sections each user has on their Home, in which order (sort_order) and whether they are hidden (is_active=0). Hiding is NOT uninstalling: the row stays. |
app_user_widgets |
Per-user widget layout: order, size and whether it is hidden. Same shape as app_user_sections on purpose — a widget and a section are configured identically. |
app_users |
The people who can log in. person_id links an account to its row in people_persons, which is what ties a login to a face in the photos. The live copy of this lives in the Pi's ajustes.json; this table is the normalized projection of it. |
app_widgets |
CATALOG of Home widgets, with their default size in grid columns × rows (default_cols/default_rows). Adding a row here makes the widget appear for everyone. |
| FINANCE | |
fin_accounts |
CHART OF ACCOUNTS of the double-entry ledger: assets, liabilities, income and expense, nested via parent_id. Derived from the raw cash book (fin_movimientos), which stays untouched — see docs/FIN_DOUBLE_ENTRY_PLAN.md. |
fin_cartera_fiscal |
Tax lots (basis of the capital-gains FIFO) with costs: comision/gasto_divisa/otros_gastos. |
fin_categories |
DIMENSION of income/expense categories (PK=code; ISO 20022 purpose_code + own subcode + merchant). |
fin_category_overrides |
Manual corrections to automatic categorisation, keyed by the normalised concept. A human decision that beats the rule and survives re-imports — this is what makes the classifier coachable. |
fin_cotizaciones |
Latest quote per ticker/broker. precio=fundamental (market); calc_valor_eur=derived (shares×price×fx). |
fin_cotizaciones_hist |
Close-price history downloaded from Yahoo (external source, not computed). |
fin_crypto_trades |
Crypto trades. Generic exchange (Kraken today; extensible to other exchanges). |
fin_cuenta_alias |
Crosswalk: statement text → fin_cuentas (per source). |
fin_cuentas |
DIMENSION of own accounts (bank |
fin_docs |
Ingested financial documents (dedupe by sha). |
fin_facturas |
Utility invoices (provider/period/amount/kwh). |
fin_manual_entries |
One-off income/expense facts with no fin_movimientos row at all (e.g. a freelance invoice paid outside the tracked accounts, an estimated tax contribution) — a transaction-shaped fact pointed at a real category, generic enough for any such one-off, not modeled around any specific source. |
fin_movimientos |
UNIFIED bank cash book (every connected account/source merged; a source's internal envelope, if any, goes in origen) — permanent raw import layer, unchanged by the double-entry ledger built downstream of it (fin_accounts/fin_transactions/fin_postings). Internal-transfer/broker classification is structural there now, not a stored code. |
fin_ops_broker |
Broker operations (BUY/SELL of securities), canonical (import_ops_broker.py). |
fin_posiciones |
Current portfolio positions (from connected broker/bank captures). |
fin_positions_hist |
DERIVED: monthly valuation of the portfolio (today's shares × that month's close) — what draws the net-worth chart. calc_close is the monthly rollup of fin_cotizaciones_hist (Yahoo's daily closes). Was calc_pos_hist: calc_ marks derived FIELDS, not a domain, and this is finance. |
fin_postings |
The lines of each transaction: amount (in minor units — cents, never floats) against an account. The double entry itself; a transaction's postings always balance. |
fin_rules |
Concept→category classification rules. |
fin_saldos |
Balance snapshots per account (available/booked) — from bank captures. |
fin_splits |
Stock splits (ratio per date) to adjust historical share counts. |
fin_suecia_acciones |
Sweden years: stock capital gains per year (K4). calc_resultado_sek=sale−cost. |
fin_suecia_ingresos |
Sweden years: ANNUAL tax summary from that jurisdiction's own tax authority. sek fundamental; calc_eur derived (×fx). |
fin_suecia_saldos |
Sweden years: balance snapshots (SEB/Avanza) at Dec-31. |
fin_transactions |
One row per economic EVENT of the ledger (date, description, origin). The amounts are not here: they live in its postings, which must sum to zero. |
fin_valor_alias |
Crosswalk: statement text → fin_valores (per source). |
fin_valores |
DIMENSION of securities (name/ticker/isin/currency/market). |
| TAXES | |
tax_declarations |
Spain IRPF returns (Modelo 100) reconciled against form 0424. (Skatteverket lives in fin_suecia_*.) |
| HEALTH | |
health_conditions |
Diagnosed conditions, with date, current status and who diagnosed them. |
health_documents |
Index of health documents (reports, tests) — the path on disk, never the content. |
health_measurements |
Time series of every measurement (weight, blood pressure, glucose…): metric says which, value/value2 hold it (two for pairs like systolic/diastolic). |
health_prescriptions |
Prescribed medication: dose, schedule and whether it is still active. |
health_profile |
Key/value with the basics of the health profile (blood type, allergies…). One row per fact, so adding one needs no migration. |
health_screen_time |
Screen time per app and day, from Apple Screen Time. Seconds, per device. |
health_visits |
Medical appointments: specialty, doctor, place and reason. |
| PEOPLE & GENEALOGY | |
people_email_stats |
RAW pool: person↔addresses with mail counts (to curate → people_person_emails). |
people_entities |
RAW pool: entities (people/companies) extracted from mail. |
people_faces |
RAW pool: detected-face index (idx ↔ Immich person id). |
people_immich_counts |
RAW pool: Immich person id with photo count. |
people_name_contexts |
RAW pool: name contexts. |
people_person_emails |
1:N dimension — a person's email addresses. |
people_person_faces |
1:N dimension — Immich faces (person_id) linked to a person. |
people_person_phones |
1:N dimension — a person's phone numbers. |
people_persons |
MASTER of persons (family tree). Data: birth/death (DATE + city), profession. Aliases: main_alias + other_aliases. Tree: father_id/mother_id (self-FK). Derived: calc_main_email, calc_age (years, (death or today)−birth). |
people_work_contexts |
RAW pool: work contexts. |
| HOME (house + network) | |
home_devices |
Network/home-automation devices (MAC, IP, kind, room). |
home_plan_arcs |
Arcs of a circle on the plan — a door's swing, mostly. |
home_plan_areas |
Polygons filled on the plan (rooms and zones drawn as an area, not as walls). |
home_plan_categories |
DIMENSION of what a plan line can be (wall, door, window…), grouped by grp. Drives its colour and meaning. |
home_plan_circles |
Circles on the plan (columns, round elements). |
home_plan_hinges |
Hinge points: where an arc pivots, i.e. which side a door opens from. |
home_plan_lines |
Plan SEGMENTS between two nodes: walls, doors, windows… cat_code says what it is and layer which layer it is drawn on. calc_orientation is derived from its angle. |
home_plan_nodes |
The plan's VERTICES (x/y in px). Everything else references these, so moving a corner moves every wall that touches it. |
home_plan_orientations |
The plan's dominant directions (degrees), used to snap walls to the flat's real orthogonal grid. is_dominant marks the main one. |
home_plan_points |
Points/icons positioned on the plan (px). |
home_property |
The home (global plan/surface metadata). |
home_room_sides |
Which lines make up each room's outline, in order. calc_rms is derived (fit against the orientation grid). |
home_rooms |
Rooms with plan polygon. plan_area_m2=FUNDAMENTAL (brochure); calc_area_m2/calc_area_delta_pct=derived. |
| PHOTOS (incl. dating + Immich mirror) | |
photo_assets |
The photo/video INVENTORY: one row per file, with its path, size, kind and the folder it came from. The base layer everything else in the domain points at. |
photo_date_applied |
The date actually APPLIED to each photo, with its source and confidence — and prev_date/prev_xmp_b64, the previous state, which is what makes it reversible. |
photo_dating_evidence |
All the date EVIDENCE gathered per photo, each source in its own column (EXIF, Takeout, email, filename, Immich, filesystem…). Nothing decided here — this is the raw material for the rule of the minimum. |
photo_dedup |
Duplicate detection by sha256: which copy is kept and which zone each one lives in. |
photo_email |
Photos found as email attachments: sender, date and subject of the message that carried them — often the only surviving date for old ones. |
photo_fb_album_names |
Facebook album id → its name. Kept apart because the export splits them. |
photo_fb_albums |
Facebook albums as exported: folder, id and representative photo. |
photo_ocr |
Text read from images (OCR). What lets a screenshot be searchable by its content. |
photo_takeout_json |
RAW layer of the Google Takeout sidecars (photoTakenTime, coordinates). Google's own claim, imported as-is and never edited. |
photo_timeline |
Each photo's assigned period/category, with confidence. The curated result of the dating. |
photo_triage |
Photos assigned to a review album — the working queue of what still needs a human eye. |
| CHAT / MESSAGING (Matrix-normalised) | |
chat_events |
Every message as an EVENT, the Matrix way: an append-only log rather than an editable table, so a chat's history is what happened, in order. |
chat_rooms |
The CONVERSATIONS (Matrix room model): one row per chat, individual or group. persona_id links a room to a person in people_persons — the only place that link is stored. |
chat_senders |
Who sends in each room. Kept apart from people_persons because a sender is a phone number until someone decides which person it is. |
| INVENTORY | |
inv_inventory |
Filesystem INVENTORY: one row per file with its path, size, dates and probable type. The raw scan the archive's curation works from. |
| DECLOUD PROGRESS | |
decloud_areas |
The decloudification areas (email, photos, calendar…), each with its weight and status. What the global percentage is computed from. |
decloud_snapshots |
Historical snapshots of that percentage, to see the trend over time. |
| DB EXPLORER (own bookkeeping) | |
dbexp_tables |
DB Explorer's own map: row count per table and which apps own/read/write it. Recomputed from the manifests; it holds no data of yours. |
| META | |
_dominios |
Legend: domain prefix → description and source DB. |