Skip to content

Demo Schema

All guide tutorials use the demo_ecommerce schema — a multi-tenant e-commerce database with three tenants, realistic sample data, and pre-configured policies. This page documents the full schema so you can reproduce every tutorial example.

Setup

The demo stack lives at scripts/demo_ecommerce/ in the repo root. See its README for the bring-up commands and env var overrides.

Tenants

Three tenants, each with their own data in every table:

TenantDescription
acmeUser: alice
globexUser: bob
starkUser: charlie

Users

UsernamePasswordTenant attributeRole
adminchangemeAdmin (UI + API access only, no data plane)
aliceDemo1234!acmeData plane user
bobDemo1234!globexData plane user
charlieDemo1234!starkData plane user

Connect through the proxy:

sh
psql 'postgresql://alice:[email protected]:5434/demo_ecommerce'

Tables

organizations

ColumnTypeNotes
nameTEXT (PK)Tenant name: acme, globex, stark
created_atTIMESTAMPTZ

customers

ColumnTypeNotes
idUUID (PK)
orgTEXT (FK → organizations)Tenant identifier — filtered by tenant-isolation policy
first_nameTEXT
last_nameTEXT
emailTEXT
phoneTEXT
ssnTEXTMasked by mask-ssn-partial policy
credit_cardTEXTDenied by hide-credit-card policy
created_atTIMESTAMPTZ

10 customers per tenant (30 total).

products

ColumnTypeNotes
idUUID (PK)
orgTEXT (FK → organizations)
nameTEXT
descriptionTEXT
priceNUMERIC(10,2)Public price
cost_priceNUMERIC(10,2)Denied by hide-product-financials policy
marginNUMERIC(5,4)Denied by hide-product-financials policy
created_atTIMESTAMPTZ

20 products per tenant (60 total).

orders

ColumnTypeNotes
idUUID (PK)
orgTEXT (FK → organizations)
customer_idUUID (FK → customers)
statusTEXTpending, processing, shipped, delivered, cancelled
total_amountNUMERIC(10,2)
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

~34 orders per tenant (~102 total).

order_items

ColumnTypeNotes
idUUID (PK)
order_idUUID (FK → orders)No org column — see note below
product_idUUID (FK → products)
quantityINTEGER
unit_priceNUMERIC(10,2)
created_atTIMESTAMPTZ

payments

ColumnTypeNotes
idUUID (PK)
order_idUUID (FK → orders)No org column — see note below
amountNUMERIC(10,2)
payment_methodTEXTcredit_card, bank_transfer, paypal
statusTEXT
processed_atTIMESTAMPTZ
created_atTIMESTAMPTZ

support_tickets

ColumnTypeNotes
idUUID (PK)
orgTEXT (FK → organizations)
customer_idUUID (FK → customers)
subjectTEXT
statusTEXTopen, in_progress, resolved, closed
created_atTIMESTAMPTZ

~50 tickets per tenant.

Tables without an org column

order_items and payments reference orders via order_id but don't carry their own org column. In policy_required mode, tables without a matching policy return zero rows by default (safe default). The guide tutorials only query customers, orders, products, and support_tickets.

Pre-configured policies

PolicyTypeEffect
tenant-isolationrow_filterorg = {user.tenant} on customers, orders, products, support_tickets
mask-ssn-partialcolumn_maskcustomers.ssn → last-4 masking
mask-ssn-fullcolumn_maskcustomers.ssn[RESTRICTED] (created but unassigned by default)
hide-credit-cardcolumn_denyRemoves customers.credit_card from all queries
hide-product-financialscolumn_denyRemoves products.cost_price and products.margin
admin-full-accesscolumn_allowFull access on all tables (created but unassigned — assign per user in the admin UI)

tenant-isolation, mask-ssn-partial, hide-credit-card, and hide-product-financials are assigned with scope=all to the demo_ecommerce datasource by setup.sh.

Quick verification

After setup, each user sees only their tenant's rows:

sql
-- As alice (acme tenant):
SELECT DISTINCT org FROM orders;
-- → acme

-- SSNs are masked:
SELECT first_name, ssn FROM customers LIMIT 3;
-- → Alice, ***-**-1234

-- Credit cards are hidden:
SELECT credit_card FROM customers;
-- → ERROR: column "credit_card" does not exist