# Registration and identity test flow

The local registration form can create a test account directly with the supplied mobile number and password, without sending an SMS or asking for an OTP. It labels this as a test and does not claim that mobile ownership was verified.

## Current activation status

On 2026-09-29, the user requested removal of SMS verification for testing. The isolated `sandbox-registration` function is deployed on `wlsxzyeernwtsetzyltq` and the localhost application is enabled in `direct-test` mode until **2026-10-06T15:57:24.350Z**. The mode requires both the sandbox flag and `PLANCK_REGISTRATION_TEST_SKIP_OTP=true`. Public/production hosts do not enter this mode. Expiry stops new test registrations; it does not delete previously created test accounts.

On 2026-09-25, the live Auth log for the failed local signup reported `500: Invalid payload sent to hook` from `send-sms-melipayamak`. The submitted number differed from the adapter's configured single test recipient, which its allowlist rejects with HTTP 400. Supabase wraps that hook rejection as HTTP 500. The application now reports upstream service failures without incorrectly blaming registration details. Neither the recipient restriction nor phone-verification requirements were changed by this diagnostic fix.

## Boundaries

- Enabled only when `NODE_ENV=development`, the request is to localhost/loopback, `PLANCK_REGISTRATION_TEST=true`, an unexpired `PLANCK_REGISTRATION_TEST_UNTIL` exists, and a server secret of at least 48 characters is configured.
- Direct mode additionally requires `PLANCK_REGISTRATION_TEST_SKIP_OTP=true` and limits creation attempts to five per minute in the local server. It never enters the SMS or OTP route.
- The optional older fixed-code mode (skip flag off) uses code `123456` and holds pending data in server memory for ten minutes, bound to an HttpOnly cookie and phone. It is not the active local flow.
- The isolated `sandbox-registration` Edge Function uses Auth's create-only admin API. Duplicate phones are rejected. Existing users are never updated or confirmed by this adapter. Password login and account recovery continue to use normal Supabase Auth.
- The function requires an independent server secret and expiry, refuses browser-origin requests, filters user metadata, and records `phone_verification_mode=sandbox` in trusted `app_metadata`.
- Supabase issues the session through the normal password grant after account creation. Session tokens remain in HttpOnly cookies. The function never returns service-role credentials or session tokens.
- Direct signup stores the entered email as contact metadata. It does not send confirmation email or mark it verified. New test accounts sign in using mobile number and password; email sign-in requires a separately connected, verified email. The existing project has no custom SMTP configured.
- Sandbox phone confirmation is not proof of number ownership or verified identity. Admin notifications identify it as a test registration. KYC approval, real inquiry evidence, role checks and administrator MFA remain required.

## Configuration

Deploy `supabase/functions/sandbox-registration/index.ts` with JWT gateway checking disabled for this function only; the function verifies its own secret. Its secrets are `SANDBOX_REGISTRATION_TOKEN` and `SANDBOX_REGISTRATION_UNTIL` (ISO timestamp). Supabase provides the service-role key inside the function; it must not be copied into the marketplace environment.

The marketplace uses the same `SANDBOX_REGISTRATION_TOKEN`, plus `PLANCK_REGISTRATION_TEST=true`, `PLANCK_REGISTRATION_TEST_SKIP_OTP=true`, and `PLANCK_REGISTRATION_TEST_UNTIL` with the same expiry. Keep all of these server-only and out of source control. Example configuration remains disabled by default.

To return to real SMS, set `PLANCK_REGISTRATION_TEST=false`, remove the temporary secret, and disable/remove the isolated function. The normal registration and OTP handlers remain intact. Starting real SMS registration clears a stale sandbox cookie.

## Inbox database

Apply in order:

1. `supabase/migrations/202609200001_identity_review_levels.sql`
2. `supabase/migrations/202609250001_identity_notifications.sql`

The second migration adds private admin events and per-admin read receipts. Customer messages share the existing private inbox used by the bell and `/account/notifications`. Registration and KYC submission generate admin events. Approval, correction notes, inquiry outcomes and other administrator messages generate customer events. Manual messages are audited and idempotent. Historic customers are searchable without retroactively sending them a new welcome notification.

Applied and schema-verified on project `wlsxzyeernwtsetzyltq` on 2026-09-25: two RLS-protected admin tables, five admin RPCs, and three notification triggers.

Applied `202609290001_direct_registration_notice.sql` on 2026-09-29. This only makes the trusted sandbox registration notification say that SMS was skipped; it does not rewrite previous messages or change permissions.

Live verification on 2026-09-29 succeeded with the isolated fixture `qa_no_sms_20260929`: direct registration, customer dashboard and welcome message, logout, password sign-in, and duplicate-phone rejection. Database verification found exactly one customer profile and one sandbox-labeled admin registration event for that fixture. No real customer's credentials or identity decision were changed. Browser verification showed the direct registration form without an OTP step.

## Interactive test

1. Open `http://localhost:3000/?auth=register`. Use the registration tab after signing out if a customer is already signed in.
2. Check that the test-mode notice and «ثبت‌نام و ورود» button are visible. Enter a new phone and registration details. Successful signup signs in immediately; no code is requested. Existing phone numbers are rejected by the create-only path and must use password login.
3. Continue to `/account/profile`, complete the identity fields, upload the required documents and submit the user's consent.
4. Sign into the administrator at `http://localhost:3001/?section=notifications` using the existing password and MFA. Follow the new request to its review page.
5. Send a correction or ordinary message to that customer. The message should appear in the customer's bell and inbox within 20 seconds while the page is visible, or on focus/refresh.
6. Review the actual evidence. Document approval does not manufacture successful identity or mobile-ownership inquiries. The customer sees the current state and review notes.
7. Mark a customer message read; the unread count updates in the inbox, bell and other open customer tabs.

Automated coverage: authentication, temporary registration scope/expiry/replay/duplicates, private inbox ownership, owner+MFA authorization, review evidence gates and message idempotency. No real customer's KYC decision is made by the automated tests.
