# Temporary identity approval under manager responsibility

Migration `202609290006_temporary_identity_approval.sql` adds a separate, expiring administrative grant. The default in the application is **7 days (168 hours)**; the RPC accepts only 24, 72, 168, or 720 hours. This mechanism does not claim that an identity, mobile-owner, or bank inquiry succeeded.

## Decision and data contract

`marketplace_identity_temporary_review(p_id,p_version,p_level,p_hours,p_reason,p_accept_responsibility)` requires owner + AAL2, a current request/version, level `primary` or `full`, an explicit responsibility acknowledgment, and a reason of 10–1000 characters. It returns the existing `marketplace_identity_admin` object.

Only the latest submitted request can receive a temporary grant. Customer consent, the current confirmed phone, and both actually uploaded identity images must exist. Draft, rejected, superseded, stale, suspended, closed, self, and staff-account requests cannot receive this grant. Real inquiry results and human document-review checkboxes are not rewritten. The approval cannot downgrade or replace an already sufficient permanent level: `temporary_level_not_upgrade` is returned when the earned standard grant already meets or exceeds the requested temporary level.

Both the identity request and dashboard account carry:

- `verification_mode`: `standard` or `temporary`
- `temporary_level`: `primary`, `full`, or null
- `temporary_expires_at`: ISO timestamp or null

The request additionally records `temporary_approved_by`, `temporary_approved_at`, and `temporary_reason`. The customer response strips the approver identifier. The administrator response retains it. The normal `account_level` / `verification_level` and verified status reflect the **effective** level; all UI surfaces must therefore use `verification_mode` to label a temporary grant and show its expiry instead of displaying an unqualified permanent-verification badge.

`final_approved_level` remains exclusively the genuine, evidence-backed permanent grant. A temporary `full` grant above an earned permanent `primary` level does not overwrite the permanent grant. Temporary approval never marks a bank verified.

`marketplace_identity_temporary_revoke(p_id,p_version,p_reason)` removes only the temporary grant and restores the currently earned permanent level or basic/pending. It requires owner + AAL2, matching version, a 10–1000 character reason, and the same protected-account safeguards. Ordinary final approval or rejection also clears temporary metadata; ordinary approval still requires its original evidence gates. Genuine document review may continue while a temporary grant is active.

Errors: `not_authorized`, `invalid_temporary_review`, `identity_conflict`, `temporary_evidence_required`, `temporary_level_not_upgrade`, `access_protected_account`, `account_suspended`, and `account_closed`.

## Expiration and integrity

Expiration is enforced in the database at protected customer access, read, and financial use, plus administrator profile/request/queue reads. It does not rely on the browser timer or a scheduled task. The existing migration-005 public access wrappers remain in place; their shared guard now synchronizes temporary identity first. Service-backed wallet and deposit-initiation checks therefore also synchronize expiry for the trusted customer subject. Order/withdrawal settlement checks synchronize it before consulting the account; referral settlement does so when examining an existing order.

After expiry, the persisted request and account return to the currently valid permanent grant, or basic/pending when none exists. All active temporary metadata is cleared. Subsequent reads do not repeatedly create expiry events. An existing permanent primary grant survives expiry of a temporary full grant. If its underlying permanent evidence has been revoked, it does not silently return merely because the temporary grant ended. Removing required images or changing the phone invalidates the temporary grant as well.

Like any time-dependent entitlement, a raw table snapshot can remain stored until the next authoritative use/read synchronizes it. Applications must use the protected RPCs or `customer_access_assert`; future trusted services must not interpret a raw `account_level` column without validating mode/expiry or invoking synchronization first. Existing authenticated clients cannot directly read those private tables.

`identity_temporary_history` is append-only, with the administrator, reason, responsibility acknowledgment, request version, and before/after levels. Customer-profile activity and the regular audit log retain each grant, revocation, conversion, invalidation, and expiry. Automatic lifecycle events are informational rather than a new pending review queue. User notifications explicitly distinguish temporary approval from inquiry success, and report expiration or conversion. Decision, effective level, audit history, and notice are atomic: a notification failure rolls back the decision.

## Validation

`node --test tests/identity-temporary-approval-db.test.mjs` runs against local synthetic fixtures with migrations 003 and 005. It checks authorization, explicit responsibility, all duration/reason/version gates, real-upload prerequisites, unchanged inquiries/checklists, visible scoped metadata without approver IDs, truthful notifications, expiry on customer/admin reads and financial use, preservation of a permanent grant, revocation, standard conversion/rejection, phone/photo invalidation, retained access restrictions, immutable history, and atomic rollback. Expiration tests fast-forward only the synthetic fixture's grant metadata. No real customer is approved or modified by these tests.
