Project lifeos data spine
FINAL ARCHITECTURE (decided 2026-06-15, supersedes interim-tool notes below)¶
- Surface = custom build,
workspace.justinsforge.com. Justin is building the legit app himself (like finances.justinsforge.com), NOT adopting Directus/NocoDB. He explicitly rejected interim/ride-on tools and learning curves on software that won't be kept. Do NOT recommend Directus/NocoDB again as primary surface or admin backend. - Multi-tenancy = workspaces. One app with a workspace switcher (Notion-style). Workspaces: Personal, Nova, JustinWieb (single-user, his) + Gus Outdoor, Gus The Bass, Sip-N-Serve (multi-user). Michael scoped to Gus workspaces, Kristine to Sip.
- Owner god-view: Justin is a member of EVERY workspace with an owner role that bypasses workspace scoping (sees all, like a Notion workspace owner). Others are scoped to theirs.
- Permissions: Justin owns this himself. Foundation: Cloudflare Access (front door, already runs it) + Postgres Row-Level Security (enforces workspace walls at the DB level). Model is one
workspace_idper row + amembershipstable (user x workspace x role). - Build-vs-adopt rule (Justin's): build it yourself UNLESS an outside authority dictates the structure. Tasks/habits/docs/projects/CRM/customers = build. Books/tax = adopt (ERPNext stays), because tax law is the outside authority. AI lowers build cost but NOT the cost of being wrong on tax.
- Personal finance: finances.justinsforge.com already won; Firefly III/Actual Budget are own-copy downgrades, never adopt them, only steal features (e.g. auto-categorization rules).
- Working method for custom build: Justin supplies the product opinions (he knows Notion well enough); Claude surfaces each product fork + how mature tools chose and why (as rationale reference, not adoption), Justin decides, Claude builds.
Decision reached 2026-06-15: build forge-data LXC hosting one lifeos Postgres + pgvector. All structured life data lives there in domain schemas: finance, commerce, tasks, fitness, health, food, home, content, contacts. Existing finance.db, datalayer.db, context.db migrate in as first drawers. Redis sits beside for scratch/caching. Words (notes, docs, memory/*.md) stay in Git/AppFlowy. ERPNext stays as accounting engine and feeds the spine rather than being replaced by it. Notion gets demoted to optional window, eventually retired once a self-hosted UI (Directus or NocoDB for rows, AppFlowy for notes) proves out.
Phasing logged in memory/daily/2026-06-15.md:
1. Stand up forge-data + Postgres + pgvector, offsite backup first
2. Migrate finance.db (lowest risk)
3. Move LifeOS off Notion-direct; brain writes Postgres, n8n proxy retires
4. Move /recall onto pgvector
5. UI bake-off: Directus/NocoDB/Grist for rows, AppFlowy/Anytype for notes
6. Cut Notion sync once replacement proves out
Inventory journal for Justin to fill: memory/plans/lifeos-data-inventory-journal-2026-06-15.md + Drive doc.
Why: Notion is rented storage with a limited API and brittle property-name contracts. finance.db/datalayer.db/context.db are already local-first but siloed and can't cross-reference. One Postgres makes all life data cross-queryable (fitness vs food vs finance vs tasks).
How to apply: Before designing any new data storage for tasks/habits/fitness/food/contacts, assume it lands in the lifeos Postgres. Check if the spine plan has moved forward before building new SQLite files.
[auto-memory session e6a507d7-a10a-468c-812b-333c77bb093a, confidence 0.85, mode direct]
Auto-memory addendum 2026-06-15T13:18:22.619786¶
Justin decided (2026-06-15) to build forge-data, a dedicated LXC running Postgres + pgvector, as the canonical data spine for all structured life data under the database name lifeos.
Decision: One Postgres, one backup, one connection for AI. Domains are organized as schemas: finance, tasks, fitness, food, home, commerce, inbox, contacts. Existing SQLite files (finance.db, datalayer.db, context.db) migrate in as first drawers.
ERPNext relationship: ERPNext stays as the books/tax engine, fed from the spine via the existing forge_erpnext_daily_post.py posting engine. ERPNext is a downstream copy, never the source of truth.
Notion: Demoted to an optional view. Tasks, habits, inbox, projects migrate off Notion-direct writes once the spine + a ride-on UI (Directus or NocoDB) proves out.
Tool split: - Ride-on tools (Directus/NocoDB) for domains with no outside authority (tasks, habits, contacts, food) - Custom apps (like finances.justinsforge.com) for domains Justin cares about deeply - ERPNext stays for accounting (tax law = outside authority, don't rebuild) - Sharing via Cloudflare Access + Directus/NocoDB built-in roles; no Notion needed
Words vs rows boundary: AppFlowy or Anytype for notes/docs; Postgres spine only for row data.
Why: Justin has been building toward this for months (finance.db, datalayer.db, context.db are three partial implementations of the same instinct). Postgres unifies them and enables cross-domain queries that no SaaS can answer.
How to apply: When building any new structured data store, default to the lifeos Postgres spine rather than a new SQLite file or Notion DB. Check forge/data/finance/COORDINATION.md before touching finance schema. The data inventory journal lives at memory/plans/lifeos-data-inventory-journal-2026-06-15.md and in Drive.
[auto-memory session e6a507d7-a10a-468c-812b-333c77bb093a, confidence 0.85]