# Customer dashboards

Local account: http://localhost:3000/account

Local assets: http://localhost:3000/wallet

Local administration remains a separate app at http://localhost:3001/. Customer login does not grant administrative access.

## Applied Supabase migrations

Applied on 2026-09-08 to `wlsxzyeernwtsetzyltq`:

- `202609080001_customer_dashboard.sql`: 16 new private tables and two customer-scoped RPCs.
- `202609080002_customer_theme.sql`: validated light/dark preference, preserving existing preference values.

Live catalog verification after installation: all 19 existing tables in `marketplace_private` have RLS enabled, zero are readable by `anon`, and zero grant direct UPDATE to `authenticated`. The 19 include three existing administration/authentication tables. No sample balances, transactions, banking details or reference-screenshot identities were inserted.

For a fresh environment, apply the marketplace and customer-auth migrations before these two files. Their installation is transactional and repeatable; production changes should be applied through the trusted migration pipeline.

## Stored data

| Area | Private tables |
| --- | --- |
| Profile and settings | `accounts`, `preferences` |
| Banks | `bank_accounts` |
| Notifications and price alerts | `notifications`, `price_alerts` |
| Invitations and rewards | `referral_codes`, `referrals` |
| Customer API access | `customer_api_keys` |
| Wallet addresses and holdings | `wallet_accounts`, `asset_positions` |
| Financial history | `transactions`, `orders` |
| Credit and staking | `credit_positions`, `staking_positions` |
| Device activity and changes | `session_activity`, `dashboard_audit` |

Supabase Auth owns passwords, verified contact methods and sessions. They are not duplicated in dashboard tables. The earlier customer-profile table owns username lookup. Only bank name, checksum-validated IBAN and optional last four card digits are collected. Identity status and level are server-controlled; complete identity documents, full card numbers, CVV, private wallet keys and OTPs are not stored here.

## Access boundary

`GET /api/dashboard` and `POST /api/dashboard` verify the HttpOnly customer session with Supabase Auth. Mutations require same-origin JSON and have bounded, whitelisted payloads. The server calls `marketplace_dashboard` or `marketplace_dashboard_update` with the customer's JWT and the publishable key. The database derives ownership from `auth.uid()`; callers cannot nominate another customer.

The private tables do not grant customers direct access. Security-definer RPCs use an empty search path and explicit qualified references. Customer writes are limited to profile, preferences, pending bank registration, bank selection/removal, notification read state, paused price alerts and revocation of an existing API key. A per-user transaction lock protects limits and primary-bank selection. Each accepted mutation is audited. Balances, transactions, verification status, account levels, API hashes and session identifiers cannot be set or retrieved through arbitrary client payloads.

## Connected and deferred workflows

Profile edits, preferences (including theme and locale), bank registration, notification read state, saved price alerts and API revocation are connected to Supabase. The header profile/name and wallet icons open the corresponding dashboards while preserving desktop hover previews. The app button becomes icon-only with the compact navigation. Language selection is only in account settings; additional languages remain disabled until their complete UI translations are approved.

Financial tables are a protected data contract for the future authoritative transaction service, not a complete accounting ledger or payment engine. Trusted services must populate holdings, transactions, orders, credit/staking positions, referrals, API metadata, notifications and device activity. Empty tables produce explicit empty states. New payments, withdrawals, credit applications, staking, API issuance, reward distribution and delivery of price alerts remain unavailable until their services are integrated. No successful payment, bank verification, reward or credit approval is simulated.

Theme is applied across the marketplace and customer dashboards, retained on the device for visitors and saved to Supabase for signed-in customers. The initial theme script is a same-origin static file allowed by the existing CSP; it applies the saved theme before paint without dynamic nonce hydration differences. Reduced-motion settings also apply throughout the site.

## Verification

46 application tests pass, including real PostgreSQL behavior through PGlite for owner isolation, anonymous denial, direct-table restrictions, validated writes, bank checksums, hidden API secrets, protected financial data and exact numeric strings. Type checking and the production build pass. Live Supabase installation and table privileges were verified. Local route response checks cover home/account/settings/wallet and rejection of anonymous dashboard API access. Browser visual and interaction QA has not been performed for these changes; deployment to the hosted site was not requested.
