Skip to content

HO Demo Seed

The HO tenant (T0ADQ6UAVKR) is the primary sandbox for VERA development and smoke testing. A daily reseed keeps it in a known, clean state so each session starts from a predictable baseline.

What the daily reseed does

lib/demo-seed.js runs automatically at 8:50 AM ET every weekday (10 minutes before the 9 AM morning briefing fires). It:

  1. Regenerates TSVs from generate-dummy-data/generate-v2.js (fresh random hours/budgets each run; names are stable).
  2. Acquires a Postgres advisory lock to prevent concurrent runs.
  3. Wipes all mutable tables for the HO tenant in FK-safe order: proposal_liabilitiesproposal_rolesproposals (these must go first — proposal_liabilities.vendor_user_id hard-FKs users with no ON DELETE clause, so any surviving row blocks the users wipe and rolls back the entire seed), then conversations, time_entries, budgets, pending_pto, unresolved_items, liabilities, rate_history, project_tasks, projects (children then parents), users, tasks, clients, disciplines, company_calendar.
  4. Re-inserts from TSVs in dependency order (disciplines → clients → tasks → users → projects → …).
  5. Re-appends the three preserved real users with collision-safe IDs.
  6. Seeds anchor data for the preserved users: Test Client, four anchor projects, time entries, envelopes, rate history, PTO requests, unresolved items, and a vendor scenario.

Scheduled by initDemoSeed(TENANTS) called at boot in index.js.

Manual reseed

DM VERA !test seed as an owner on the HO tenant. VERA replies with a summary of tables wiped and rows inserted.

If HO state gets messy mid-day, !test seed is the fastest recovery path.


Preserved real users

These three users are never wiped — their rows are read before the wipe and re-appended after.

Slack IDNameRole
U0AEJHN3MNVTom HartOwner
U0AKQ2EDWAUMTHManager
U0AJTN12DPYUTHUser

The generator produces a Tom Hart row with a fake Slack ID (U0000000001). That row is discarded during the merge; the real Tom Hart row (with the real Slack ID) takes its place.


The cast of characters

Generated users (15)

These users are produced by generate-v2.js on every reseed. Names are stable; budgets and hours vary.

IDNameRoleTypeNotes
1Tom HartOwnerFTEPlaceholder — replaced by preserved Tom Hart
2Rachel KimOwnerFTESecond owner
3Sarah ChenManagerFTEPM archetype: consistent under-budget pace
4Mike JohnsonManagerFTEPM archetype: aggressive pace, often over
5Alex KimUserFTE
6Nina FosterUserFTE
7Priya PatelUserFTE
8Lena ZhaoUserFTE
9Chris TaylorUserContractor20 h/wk
10Marcus WebbUserContractor20 h/wk
11Jamie ParkUserContractor20 h/wk
12David OkonkwoUserContractor20 h/wk
13Amy WalshUserContractor20 h/wk
14Talia RodriguezUserVendorSells deliverables; logs no time
15Jordan ReedUserVendorSells deliverables; logs no time

Plus the three preserved real users (Tom Hart at real Slack ID, MTH, UTH) appended after the generated set.

Disciplines (6)

Six disciplines are seeded, each carrying a default_task_id that maps 1:1 to the corresponding task. This ensures every client time entry is categorised in the By-discipline segmentation view with zero Unmapped rows.

IDNameDefault task
1DesignDesign (task 2)
2DevelopmentDevelopment (task 3)
3StrategyStrategy (task 1)
4CopywritingCopywriting (task 4)
5Project ManagementProject Management (task 5)
6QA & ReviewQA & Review (task 6)

Task 7 (Admin) is internal-only and intentionally has no discipline — internal projects are excluded from segmentation.

Clients (11)

NameNotes
InternalRequired infrastructure — always id=1
Meridian HealthRetainer client
Harbor LogisticsRetainer client
Bloom RetailFixed Price client
Pulse AnalyticsT&M client
FreshFarmFixed Price client
CityCoreT&M client
Nexus MediaFixed Price client
SkyBridgeT&M + Fixed Price client
Apex FintechRetainer client
Future Forward FundPro Bono client

Generated projects (canonical shapes)

NameTypePMNotes
Admin / Internal Meetings / New Business DevelopmentInternalTom (id 1)Overhead
PTO / Sick / LeaveInternalProtected time-off projects
Meridian Health Support RetainerRetainerSarah Chen13+ completed periods + active Apr 2026
Harbor Logistics Platform RetainerRetainerMike JohnsonPacing over budget (demo alert trigger)
Apex Fintech Creative RetainerRetainerSarah Chen
Bloom Retail Brand RefreshFixed PriceSarah Chen
FreshFarm Brand IdentityFixed PriceSarah Chen
Nexus Media Campaign SuiteFixed PriceMike Johnson
SkyBridge Annual ReportFixed PriceMike Johnson
Future Forward Fund ImpactPro BonoSarah Chen
CityCore App DevelopmentT&MSarah ChenVendor liability (Talia Rodriguez, Design) — drives the By-discipline make-vs-buy face-off
Pulse Analytics DashboardT&MMike JohnsonVendor liability (Jordan Reed, Copywriting) — drives the By-discipline make-vs-buy face-off
SkyBridge Website RedesignT&MMike Johnson
Meridian Health Digital SupportT&MSarah ChenBackbone engagement — spans the full 12-month window so the Monthly P&L never falls to $0 (the frozen retainers are stripped at seed)
Harbor Logistics Platform SupportT&MMike JohnsonBackbone engagement — full-window billable base, neutral delivery position

The three retainers above are generated but stripped at seed time (Retainer/Agile creation is frozen, #962), so they do not appear in the live demo. Their continuous monthly revenue is replaced by the two full-window T&M backbone engagements, whose logged hours are spread evenly across the window (not front-loaded) so every month shows believable, non-zero revenue.

Preserved-user anchor projects

Created by seedPreservedUserData after the bulk insert. These always exist post-reseed regardless of what the generator produces.

NameTypePurpose
Test ClientClient recordParent for anchor projects
Test – Acme RetainerRetainerMTH PM; three burn states (Owner <50%, User healthy)
Test – Blue Website (FP)Fixed PriceMTH PM; User over budget; vendor scenario
Test – Agile SprintAgileMTH PM; User at warning burn
Test – Pro Bono ClinicPro BonoZero-cost project
Test – Internal OverheadInternalShared overhead project for all preserved users

Verifying a reseed worked

Run these in Supabase SQL Editor after !test seed:

sql
-- Confirm test cruft (Foo* projects) is gone
SELECT id, name FROM projects
WHERE tenant_id = 'e0c22d94-f990-5cd3-99b7-a4e2a2228147'
  AND name LIKE 'Foo%';
-- Expect 0 rows

-- Confirm cast is restored
SELECT COUNT(*) AS user_count FROM users
WHERE tenant_id = 'e0c22d94-f990-5cd3-99b7-a4e2a2228147'
  AND status = 'active';
-- Expect ≥ 18 (15 generated + 3 preserved)

-- Confirm anchor projects exist
SELECT id, name FROM projects
WHERE tenant_id = 'e0c22d94-f990-5cd3-99b7-a4e2a2228147'
  AND name LIKE 'Test – %';
-- Expect 4–5 rows (Acme Retainer, Blue Website FP, Agile Sprint, Pro Bono Clinic, Internal Overhead)

Safeguards

  • seedDemoTenant returns { success: false } immediately if tenant.id !== 'T0ADQ6UAVKR'.
  • !test seed in index.js checks tenant.id !== DEMO_TENANT_ID before calling the seed function.
  • Advisory lock prevents concurrent runs (cron + manual).
  • Every DELETE includes WHERE tenant_id = <HO UUID> as belt-and-suspenders beyond RLS.

Monitoring

Every successful seed run records a seed.daily event, visible on /status as "Demo seed (HO)". It follows the same weekday-only cadence as the morning/evening reminder checks — an amber reading early Monday morning (before the 8:50 AM ET run) is expected and self-heals once that run completes, not a failure to investigate.


Recovery if reseed fails

If !test seed fails mid-run, the database may be in a partially-wiped state. Re-run !test seed immediately — the wipe+insert is atomic (single transaction), so a failed run leaves the previous state intact or rolls back cleanly.

If state is unrecoverable, escalate to Tom for direct SQL intervention.