# User-data schema (data-asset-kit)

Structures user data so the company is a **sellable asset** — the retention /
conversion metrics a buyer's due diligence asks for, plus the consent + deletion
layer that makes the data legally transferable. From the registry block
`data-asset-kit`.

## Apply (Postgres / Supabase)

In order:

1. `01_core.sql` — users, consent, profiles, daily usage, deletion, retained-cohort view
2. `02_value_tables.sql` — projects → deployments (VibeCoder's funnel) + conversion view
3. `03_rls.sql` — **Row Level Security (Supabase)**. Do not skip on Supabase.

```
psql "$DATABASE_URL" -f db/01_core.sql
psql "$DATABASE_URL" -f db/02_value_tables.sql
psql "$DATABASE_URL" -f db/03_rls.sql
```

Order matters: the value tables reuse `touch_updated_at()` and reference `users`,
both from core; RLS goes last so every table exists to lock down.

**RLS is not optional on Supabase.** Without it, the auto-generated API lets any
logged-in user read or delete *everyone's* rows. For the owner-only policies to
work, each `users.user_id` must equal the user's Supabase auth id — wire `user_id`
to `auth.users(id)` (see the note in `01_core.sql`), or `auth.uid() = user_id`
protects nothing. Your server (service-role key) bypasses RLS, so exports,
deletion, and the analytics views still work; keep those views server-side only.

## Runtime

`data-asset.js` exports `createDataAsset({ query })` →
`recordConsent`, `hasTransferConsent`, `transferableCounts`, `exportUserData`,
`deleteUser`. Pass a `query(text, params)` (node-postgres `pool.query`, or a thin
Supabase adapter). Record consent at signup — **including
`data_transfer_on_acquisition`** — and gate any sale on `hasTransferConsent`.

## Before production — two human gates

1. **A lawyer confirms your Terms actually grant data transfer on acquisition**,
   for your users' jurisdiction. The schema records the consent; your Terms must
   contain the clause. *This is not legal advice.*
2. **Run these files against a scratch database once.** They parse against the
   Postgres grammar but were not executed on a live DB when generated.

The full audit is in the block's `.workbench/dd/` record (rating: CAUTION, on
those two gates).
