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,subscriptionsexist).
Steps¶
1. Create or identify the auth user¶
- 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).
- Note the
idfield for this user; you’ll need it asauth_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
idascompany_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¶
- Log out of the app.
- Log in with the owner’s email/password.
- Confirm:
- Owner can access
/owner-dashboard. - Owner-specific routes (companies, users, affiliates, analytics) render.
- Non-owner routes still work as expected.
- Owner can access
If routes are blocked, check:
user_profiles.roleisowner.user_profiles.tenant_idmatchescompanies.id.AuthProvidersuccessfully resolves tenant/role (see logs, or inspect localStoragesb-user-profile).
Rollback¶
To remove an incorrectly created owner/company in dev/stage:
- Delete dependent rows (in order):
subscriptionsfor thatcompany_id.- Any test
orders,inventory_items,clients, etc. linked to thattenant_id.
- Delete
user_profilesrow for that user. - Delete
companiesrow. - Delete
auth.usersrecord 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.