Skip to content

Database Schema Overview

VERA's database is a Google Sheet with 14 operational tabs (01–14) plus 22. Projects Master. The bot reads and writes exclusively here. Clients never see this spreadsheet.


Two-spreadsheet architecture

SpreadsheetPurposeWho accesses it
Database sheetAll operational data — tabs 01–14 + 22Bot (service account) only
Reporting sheetHuman-facing dashboardsClients and owners (no bot access)

The reporting sheet imports data from the database sheet via IMPORTRANGE. The bot never reads or writes the reporting sheet.


The schema contract

Column order is the contract. The bot reads every sheet by positional index (row[0], row[1], etc.) — not by column name. This means:

  • Never reorder columns — even one shift breaks all reads for that sheet
  • Never rename a sheet tab — tab names are string literals throughout the code
  • Never insert a column in the middle — only append at the end
  • Adding a column at the end is safe

If you need to make a schema change, it requires four simultaneous updates:

  1. The Google Sheet itself
  2. The schema documentation
  3. The column-offset code in mcp-server.js
  4. The test fixtures in tests/mcp-routes.test.js

Foreign key relationships

03. Users ──┬── user_id ──→ 01. Time Entries
            ├── user_id ──→ 07. Budgets
            ├── pm_user_id → 02. Projects
            ├── discipline_id → 08. Disciplines
            ├── created_by ──→ 07. Budgets
            ├── user_id ──→ 10. Pending_PTO
            └── affected_user_id → 11. Unresolved_Items

02. Projects ┬── project_id → 01. Time Entries
             ├── project_id → 06. Project_Tasks
             ├── project_id → 07. Budgets
             ├── client_id → 04. Clients
             ├── parent_project_id → 02. Projects (self-ref, sprints)
             └── affected_project_id → 11. Unresolved_Items

04. Clients ──── client_id → 02. Projects

05. Tasks ──┬── task_id ──→ 01. Time Entries
            ├── task_id ──→ 06. Project_Tasks
            └── task_id ──→ 07. Budgets

22. Projects Master ── project_name →→ 02. Projects.name  (string join, not ID)

Tab summary

TabPurposeKey operations
01. Time EntriesEvery logged hourAppend, edit, delete
02. ProjectsProject definitionsAppend, update various cells
03. UsersTeam membersAppend, update role/status
04. ClientsClient organisationsAppend
05. TasksWork categoriesAppend
06. Project_TasksTasks enabled per projectAppend (enable), delete (disable)
07. BudgetsPer-person hour envelopesAppend, update hours/status
08. DisciplinesFunctional rolesAppend
09. Conversations24hr chat historyAppend
10. Pending_PTOTime off requestsAppend, update status
11. Unresolved_ItemsFlagged operational issuesAppend, update status
12. Company_CalendarHolidays and eventsAppend, delete
13. Rate_HistoryHourly cost per person (versioned)Append only
14. LiabilitiesVendor payment commitmentsAppend, update status
22. Projects MasterFinancial metadata per projectAppend (on create)

See All Sheets for the complete column-by-column reference.


ID strategy

All IDs follow the same pattern:

new_id = MAX(existing ids in sheet) + 1

IDs are permanent and sequential — never reused, even when records are deleted. This ensures time entry #42 always refers to the same entry, enabling reliable audit trails and edit/delete operations via natural language.


Write-Ahead Log (WAL)

VERA uses a Write-Ahead Log pattern to handle the Google Sheets read-after-write race condition. After writing to a sheet, the new row is cached in memory so that an immediate read returns the correct data — even before Google's backend has propagated the write.

Three sheets currently have WAL protection:

  • Budgets (07. Budgets) — new envelopes, updates, and cancellations are visible immediately after write
  • Conversations (09. Conversations) — ensures conversational context is available for immediate follow-up replies
  • Time Entries (01. Time Entries) — newly logged, edited, or deleted entries are reflected in project status queries within seconds

This is why you don't see "just logged but not showing up" issues despite Google Sheets' eventual consistency model.

VERA by talktalkmake