Reference
Local database schema
Everything OOMU stores, and how. All of it lives on your Mac.
| File | oomu-beta4.sqlite |
| Engine | SQLite via SQLCipher |
| Schema version | 1 |
| Namespace | ai.eldris.oomu.gpd.beta4 |
1. Encryption
The database is encrypted with SQLCipher. Every connection opens with:
PRAGMA key='<key>';
PRAGMA cipher_memory_security=ON;
PRAGMA foreign_keys=ON;
PRAGMA secure_delete=ON;
- The key is held in the macOS Keychain, under a service namespace specific to Beta 4. It is never written to disk in plain text and never transmitted.
cipher_memory_securitywipes sensitive pages from memory.secure_deleteoverwrites deleted content rather than merely unlinking it.- After opening, OOMU verifies the database is actually encrypted before proceeding. Failure raises
data_encryption_failedrather than continuing against a readable file.
A copied database file is not enough to read your data. The key is bound to your Keychain, on this Mac.
What is not in here
Secrets. API keys, OAuth refresh tokens, and channel bot tokens live in the Keychain. The database stores only an opaque reference (credential_ref, account_binding_digest) plus non-secret metadata.
2. Schema conventions
Every table is written with constraints rather than trusting the caller.
| Convention | Example |
|---|---|
Prefixed identifiers, enforced by GLOB | project_id GLOB 'project_*', turn_id GLOB 'turn_*' |
Enumerations as CHECK constraints | data_policy IN ('local_only','cloud_permitted') |
| Digests as exactly 64 characters | CHECK (length(sha256) = 64) |
| JSON validated on write | CHECK (json_valid(metadata_json)) |
| Millisecond timestamps, ordered | CHECK (updated_at_ms >= created_at_ms) |
| Cross-field consistency | A completed activity must have receipts; a failed one must not |
The last is worth dwelling on. Illegal states are rejected by the database, not just avoided by the code above it.
3. Projects
| Table | Holds |
|---|---|
projects | Name, description, data_policy (local_only or cloud_permitted), instructions up to 32,000 characters, archive timestamp. |
project_documents | Imported files. Format is pdf, xlsx, xls, docx, csv, markdown, or text; up to 8 MB each; SHA-256; extracted markdown up to 256 KB. Unique per (project_id, sha256). |
project_document_chunks | Indexed passages with ordinal, page number, heading, content up to 4 KB, content digest, and precomputed lexical and semantic term sets. |
project_scratchpads | The Notes markdown, up to 256 KB, with a revision counter. |
project_artifacts | Links artifacts to projects, maintained by triggers on artifacts. |
recoverable_project_deletions | Staged deletions with a purge deadline. |
4. Chat
| Table | Holds |
|---|---|
chat_sessions | Title and title source, project, provider and model, context limit (2,048 – 2,000,000). |
chat_messages | Role (user, assistant, system, tool), content up to 1 MB, provider and model, metadata JSON, content digest. |
chat_attachments | Attached files with source path, source identity digest, private copy, media type, extracted text and its digest, and extraction state (complete, truncated, not_text). |
completed_turns | One row per committed turn: request digest, result JSON, result digest. |
accepted_turn_routing | The routing decision for a turn, with its digest. |
chat_artifacts | Which documents were produced in which chat, maintained by a trigger on artifacts. |
chat_context_compaction | Per chat: automatic compaction on or off, the threshold (50–90%, default 80), and the saved summary. |
chat_preferences | The agent you last selected. |
trusted_fact_sets | Verified facts a turn established, kept so a follow-up can rely on them. |
pending_chat_attachment_deletions | Private attachment copies still to be removed from disk after a chat is deleted. |
recoverable_chat_deletions | Staged deletions with a purge deadline. |
completed_turns and accepted_turn_routing are keyed by turn_id and store a request digest, which is what makes a turn replay-safe.
5. Activity and evidence
activity_records is one row per turn, with a state of queued, routing, running, verifying, completed, failed, or recovery_required.
Its constraint is the interesting part:
- completed requires
receipt_count > 0, anevidence_digest, and no failure category. - failed requires
receipt_count = 0, no evidence digest, and a failure category fromrouting,local_model,cloud_service,native_execution,persistence,setup, orunknown. - Any other state requires no receipts, no evidence, and no failure category.
A turn cannot be recorded as completed without evidence behind it. The database refuses the row.
6. Ledger
| Table | Holds |
|---|---|
model_usage_ledger | One row per turn: execution_kind (local or cloud), provider, model, and input/output token counts. |
Token counts are nullable, but only together: a row cannot have input tokens without output tokens. Where a cloud provider did not return usage, the interface reports it: "{count} cloud responses did not include token totals." It does not estimate.
7. Agents
| Table | Holds |
|---|---|
agents | Name, description, instructions, routing mode, provider and model, favorited, archived. |
agent_profiles | Personality: template, identity, communication style, traits, values, boundaries. |
agent_model_policies | Per-agent context limit (4,096 – 1,000,000) and max output (256 – 8,192). |
agent_mod_policies | Whether the agent uses all enabled Mods. |
agent_mod_bindings | Specific Mod bindings. |
chat_session_agents | Which agent is bound to which chat. |
8. Workflows and schedules
| Table | Holds |
|---|---|
workflows | Name, project, version, state, graph digest, last run. |
workflow_graphs | The compiled graph per version, with its digest, origin turn, decision digest, and capability manifest version. |
workflow_authoring_definitions | The authored definition per version. |
workflow_execution_contexts | The snapshot and envelope a version runs against. |
workflow_instances | Runs, with run_key, state, current step, output, pause reason, and error code. Unique per (workflow_id, workflow_version, run_key). |
workflow_step_runs | Per-step state, effect JSON and digest, arguments and digest, missing fields, and receipt JSON and digest. |
workflow_routines | Schedule JSON, missed-run policy and cap (1–12), required connections, controlled destinations, active flag, next run, and a lease token with expiry. |
workflow_routine_occurrences | One row per scheduled slot, unique per (routine_id, scheduled_for_ms). |
schedules | Source and normalized expression, and kind (cron or interval). |
schedule_runs | Result state and notification state per occurrence. |
recoverable_workflow_deletions | Staged deletions with a purge deadline. |
The uniqueness constraint on (routine_id, scheduled_for_ms) is what makes scheduled execution exactly-once across restarts. The lease token is what stops two processes claiming the same routine.
workflow_instances references workflow_graphs with ON DELETE RESTRICT: a graph version with runs against it cannot be deleted, so history never dangles.
9. Documents produced
| Table | Holds |
|---|---|
artifacts | Kind, display name, canonical path, byte length, SHA-256, and verification state (verified, missing, changed). |
artifact_inspections | Page, sheet, slide, and formula counts; preview key, digest, byte length, and dimensions; renderer identifier and its SHA-256. |
recoverable_artifact_deletions | Documents removed from the list, with a purge deadline. Removing a document from the list does not delete the file. |
artifact_inspections deliberately holds no filesystem path. The preview is addressed by content key, so a preview record cannot leak where a file lives.
10. Connections
| Table | Holds |
|---|---|
connections | The unified view. Kind is apple, mcp, connector, or channel; state is configured, connected, degraded, expired, unavailable, or disconnected. |
remote_connections · remote_operations · remote_oauth_attempts | OAuth connectors and their cataloged operations. |
remote_channel_accounts | Slack or Discord accounts (the provider column accepts nothing else), with a credential_ref of the form channel-secret:* and an account binding digest. Unique per (provider, account_binding_digest). |
remote_channel_destinations | The verified channel per account. |
channel_control_bindings | The one owner allowed to give commands, the bot's identity, and, for Discord, the last message already seen, so older messages are never replayed. |
channel_control_receipts | One row per accepted message: a digest of the event, a digest of the sender, the time, the command, and its state. A repeated event digest is ignored, which is how a message is handled once. Unrecognized text is stored as help, never as what was typed. |
channel_control_audit | One outcome per incoming message: accepted, non_owner_dropped, or rate_limited. Triggers reject any update or delete. |
channel_setup_progress | Where you are in the four-step setup, per app, so it resumes after a restart. |
retired_channel_secrets | Keychain references from removed channels, kept until the secret has actually been deleted from the Keychain. |
local_mcp_servers | Executables you selected, with per-tool read-only flags. |
mcp_setup_manifests · mcp_setup_connections · mcp_setup_secret_bindings · mcp_setup_secret_cleanup_obligations · mcp_setup_operations | Manifest-configured MCP connections. |
mcp_setup_secret_cleanup_obligations exists so that a secret whose connection is removed is recorded as needing removal from the Keychain, and cannot be forgotten because the delete happened between two failures.
11. Models and providers
| Table | Holds |
|---|---|
local_models | Display name, architecture, canonical path, byte length, SHA-256, device, inode, and modification time, and default flag. |
local_model_display_names | Names you gave models. |
cloud_model_connections | Provider, verified model, and an account digest. |
custom_cloud_providers | Display name, origin, endpoint path, and model IDs. |
remote_model_catalog | A signed catalog snapshot with version, ETag, and a 128-character signature. |
Recording device, inode, and modification time alongside the hash means OOMU can tell a model file that moved from one that was replaced.
12. Mods
| Table | Holds |
|---|---|
installed_mods | Name, description, version, author, category, enabled flag, integrity state (verified, invalid, missing), package digest, declared capability IDs, and declared endpoint hosts. |
installed_mod_packages | Installed root, entry point, canonical manifest JSON, trust state, file count, byte count. |
mod_tag_aliases · mod_tag_defaults | Your short alias for a Mod, and which Mod a shared alias opens, for all projects or one. |
Trust state and integrity state are separate columns because they answer different questions: who signed it, and do the files still match.
13. Memory and profile
| Table | Holds |
|---|---|
internal_memory_records | Content up to 16,000 characters, scope (global or project), and the session, turn, and goal it came from. Forgetting sets four fields together or none. A unique partial index prevents duplicate active memories with the same content in the same scope. |
profile_settings | Display name, locale, appearance (cool, creme, dark, system), cloud permitted, default provider and model. |
profile_personalization | Pronouns, role, background, timezone, languages, expertise, interests, priorities, current projects, context, response guidance, tone, length, formatting, boundaries. |
enterprise_security_settings | air_gap_mode. Seeded on creation. |
audit_security_violations | Actions an organization's policy refused, as an append-only hash chain. Triggers reject any update or delete. |
daily_briefings | One row per date, keyed YYYY-MM-DD, with the synthesized content. |
data_migration_receipts | A record that a one-time import ran, and what it brought across: row counts and digests per table for the Beta 3 import, and the Beta 2 import record that came over with it. |
analytics_consent · anonymous_telemetry_preferences | Left over from Beta 2's retired diagnostics. Nothing reads them to send anything. |
Every memory record carries its provenance. A saved fact can always be traced to the turn that produced it.
Standing memory
| Table | Holds |
|---|---|
memory_synthesis_entries | One fact: its bank (people, projects, or preferences), subject, content of up to 800 characters, revision, and the exact source quotation with its session and turn. Forget clears the content and the quotation and keeps a marker, so the fact is not distilled again. |
memory_synthesis_sources | Which of your messages have already been read, so each is distilled once. |
memory_synthesis_state | The Update overnight switch, the last attempt, and whether the files below need rewriting. |
memory_synthesis_receipts | Each update, edit, and forget, with counts of sources read, facts kept, and sources left out. |
The database is the source of truth. OOMU also keeps three encrypted files, people.json, projects.json, and MEMORY.md, in a memory folder that only your account can open, each within a fixed size budget.
13a. Mochi and Ready for review
| Table | Holds |
|---|---|
standing_interests | Each interest Mochi can watch, whether it is on, its setting (a city, a mail folder, a topic list), and any snooze. All start off. |
ambient_deliverables | The cards Mochi has prepared, and whether each is pending or dealt with. |
ambient_seen | What has already produced a card, so the same file, event, or article does not interrupt you twice. |
ambient_checks | The history behind Recent checks. |
ambient_preferences | Where Mochi reads mail and calendar from. |
staged_deliverables | Each file in Ready for review: its manifest (name, type, size, SHA-256, the task that made it, where it was meant to go), its status (staged, approved, promoted, or dismissed), any snooze, and the folder it was saved to. |
deliverable_audit | The approval history: every transition with its time, destination, and where it came from (desktop, slack, discord, or system). Triggers reject any update or delete. |
The waiting files themselves are not in the database. They sit in a private folder in the application data root, one folder per item, until they are saved or cleaned up.
14. Mutation journal
data_mutations records one row per durable change:
| Column | |
|---|---|
operation_id | Primary key, supplied by the caller. |
operation | What was requested. |
request_digest | SHA-256 of the request. |
entity_kind, entity_id | What changed. |
result_json, result_digest | What the result was. |
committed_at_ms | When. |
This is what makes the bridge idempotent. Replaying an operation_id returns the recorded result rather than repeating the change.
15. What is stored outside the database
| Where | |
|---|---|
| Secrets | macOS Keychain, service ai.eldris.oomu.gpd.beta4.credentials |
| Audit signing key | The Secure Enclave. Non-extractable. |
| Model files | The application's model folder when downloaded, or wherever you located them, referenced by canonical path and hash |
| Organization policy | /Library/Application Support/OOMU/policy.json, or managed preferences, on a managed Mac. Signed policies from OOMU Control are cached in the application data root and verified again at startup. |
| Private document and attachment copies | The application data root |
| Files waiting in Ready for review | staged/ in the application data root, until approved or cleaned up |
| Standing memory files | memory/ in the application data root, encrypted |
| The background service | A launch agent in ~/Library/LaunchAgents, only if you turned it on, and a socket in a private folder in the application data root |
| Effect journal | execution/effect-journal-v1.json in the application data root |
| Artifacts | Where they were written, referenced by canonical path and hash |
Related
- Application Bridge API: the commands that read and write this.
- Privacy & security: the reasoning behind the layout.
- Enterprise security: exporting the audit ledger.