Skip to content

Runbook: Owner Dashboard Setup

Goal: Bootstrap the initial owner account and company so a new tenant can access the Owner Dashboard and manage their store.

This runbook is intended for internal use (support/ops) when setting up a new environment or recovering from a broken onboarding flow.


Preconditions

  • You have access to:
    • Supabase project dashboard (SQL editor + auth users).
    • The Workbench AI app (deployed dev/stage/prod).
  • You know which email address should be the owner.
  • Migrations have been applied (tables like companies, user_profiles, subscriptions exist).

Steps

1. Create or identify the auth user

  1. In Supabase Auth → Users:
    • If the owner already signed up via the app, locate their user by email.
    • Otherwise, create a new user:
    • Email: owner@example.com (replace with real email).
    • Password: temporary password (send securely to the owner).
  2. Note the id field for this user; you’ll need it as auth_user_id.

2. Create a company row

In Supabase SQL editor, insert a companies row:

insert into public.companies (name, email)
values ('Example Jewelry Co', 'owner@example.com')
returning id;
  • Save the returned id as company_id / tenant_id.

3. Create a user_profile row

Link the auth user to the company and mark them as owner:

insert into public.user_profiles (id, tenant_id, role, email)
values (
  'AUTH_USER_ID_HERE',       -- from Auth users
  'COMPANY_ID_HERE',         -- from companies insert
  'owner',                   -- role
  'owner@example.com'        -- email
);
  • Replace placeholders with real values.

4. Seed a subscription row (optional for tests)

If you want the owner to have an active subscription immediately (e.g. in dev/stage), insert a row in subscriptions:

insert into public.subscriptions (
  company_id,
  plan_name,
  status,
  stripe_subscription_id,
  stripe_customer_id,
  current_period_start,
  current_period_end
) values (
  'COMPANY_ID_HERE',
  'starter',
  'active',
  null,                -- or a test Stripe subscription id
  null,                -- or a test Stripe customer id
  now(),
  now() + interval '30 days'
);

In production, this row is normally created/managed by Stripe webhooks; use manual seeding only for controlled scenarios.

5. Verify access in the app

  1. Log out of the app.
  2. Log in with the owner’s email/password.
  3. Confirm:
    • Owner can access /owner-dashboard.
    • Owner-specific routes (companies, users, affiliates, analytics) render.
    • Non-owner routes still work as expected.

If routes are blocked, check:

  • user_profiles.role is owner.
  • user_profiles.tenant_id matches companies.id.
  • AuthProvider successfully resolves tenant/role (see logs, or inspect localStorage sb-user-profile).

Rollback

To remove an incorrectly created owner/company in dev/stage:

  1. Delete dependent rows (in order):
    • subscriptions for that company_id.
    • Any test orders, inventory_items, clients, etc. linked to that tenant_id.
  2. Delete user_profiles row for that user.
  3. Delete companies row.
  4. Delete auth.users record if the account should no longer exist.

Be very careful in production. Prefer disabling access or changing roles over deleting rows, unless you’re absolutely sure.


Notes

  • The normal onboarding flow (signup + Stripe checkout) should create these records automatically. Use this runbook only when that flow is broken or when bootstrapping an environment manually.
  • After any manual DB changes, verify that:
    • RLS policies still allow the owner to read/write their data.
    • No cross-tenant data is visible.