# Validation Report: URS-055

**Title:** Restrict uncertified reps from actions until approved
**Date:** 2026-04-23T03:43:31.759Z
**Duration:** 114.9s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall restrict regulated sales actions to authorized and approved rep users only

*Source: `User_Requirement_Specifications_ZuriMED_DeviceFlow.xlsx` — the run below proves the system meets this requirement.*

## Environment

- **Inbox URL:** http://localhost:65013
- **Database:** localhost:65014/cc_repinbox_dev

## Setup

Status: ✅ PASS

## Test Steps

Each step below corresponds to one Playwright test that ran sequentially. Screenshots and video recordings provide visual evidence of the UI behaviour.

### 1. Step 1: Bill-only blocked — ✅ PASS

**What this step proves:**

An uncertified sales rep attempts to create a bill-only order. The system blocks access to the bill-only form, confirming that the certification requirement is enforced before any order can be submitted.

**Screenshots:**

![step 01 ryan dashboard](screenshots/step-01-ryan-dashboard.png)

![step 01 billing blocked](screenshots/step-01-billing-blocked.png)

**Video recording:**

[▶ Watch step recording](videos/step-01-billing-blocked.webm)

---

### 2. Step 2: Order request blocked — ✅ PASS

**What this step proves:**

The same uncertified rep attempts to submit a standard order request. The system again blocks access, demonstrating that both order types are restricted until the rep obtains manufacturer certification.

**Screenshots:**

![step 02 order request blocked](screenshots/step-02-order-request-blocked.png)

**Video recording:**

[▶ Watch step recording](videos/step-02-order-request-blocked.webm)

---

### 3. Step 3: Certified rep control — ✅ PASS

**What this step proves:**

A certified sales rep navigates through the bill-only form without being blocked. The form heading and step indicator both render, and the "Manufacturer Approval Required" warning is absent — confirming the restriction is applied only to uncertified reps.

Bob's relationship row has `active = true` in the fixtures, which is the column the gating logic (`getAvailableFulfillingOrganizations`) consults. The `status` column in the demo data may read `proposed_pending_onboarding` rather than `active` because the seed set preserves the original onboarding history — but the boolean `active` flag is authoritative for whether the rep may place orders, which is why the DB assertion in this run checks `active = true` for the control case rather than the `status` string.

**Screenshots:**

![step 03 bob billing form](screenshots/step-03-bob-billing-form.png)

**Video recording:**

[▶ Watch step recording](videos/step-03-certified-control.webm)

---

### 4. Step 4: Manufacturer approval — ✅ PASS

**What this step proves:**

A manufacturer user reviews the pending rep certification request and approves it, changing the relationship status from pending to active. This step generates the approval notification that certifies the previously blocked rep.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-04-23T03:44:11.248Z → 2026-04-23T03:44:18.786Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-04-23 03:44:15Z | user_log | rep_onboarding_request_approved | mark.manufacturer@zurimed.com | ZuriMED | — |
| 2026-04-23 03:44:15Z | transactional_email | rep_created | — | StellarTech Medical Solutions | — |

**Screenshots:**

![step 04 ryan pending](screenshots/step-04-ryan-pending.png)

![step 04 approval dialog](screenshots/step-04-approval-dialog.png)

![step 04 ryan active](screenshots/step-04-ryan-active.png)

**Video recording:**

[▶ Watch step recording](videos/step-04-manufacturer-approval.webm)

---

### 5. Step 5: Bill-only after certification — ✅ PASS

**What this step proves:**

The newly certified rep navigates to the bill-only form and is no longer blocked. The form is accessible and the order is submitted successfully, confirming that certification takes immediate effect.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-04-23T03:44:28.430Z → 2026-04-23T03:44:51.534Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-04-23 03:44:49Z | decision | bill_only_order.enqueue_upload_classification | ryan.delauintana@stellartech.com | ZuriMED | no |
| 2026-04-23 03:44:50Z | transactional_email | new_bill_only | — | StellarTech Medical Solutions | — |

**Screenshots:**

![step 05 billing form accessible](screenshots/step-05-billing-form-accessible.png)

![step 05 devices selected](screenshots/step-05-devices-selected.png)

![step 05 review](screenshots/step-05-review.png)

![step 05 order submitted](screenshots/step-05-order-submitted.png)

**Video recording:**

[▶ Watch step recording](videos/step-05-billing-submitted.webm)

---

### 6. Step 6: Order request after certification — ✅ PASS

**What this step proves:**

The certified rep navigates to the standard order request form without the approval warning, then submits a consignment order end-to-end. A DB assertion subsequently confirms that a row was persisted to the `order_requests` table — proving the post-certification path is unlocked at the database level, not just the UI level.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-04-23T03:45:01.340Z → 2026-04-23T03:45:21.755Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-04-23 03:45:19Z | decision | order_request_created | ryan.delauintana@stellartech.com | ZuriMED | yes |

**Screenshots:**

![step 06 order request form accessible](screenshots/step-06-order-request-form-accessible.png)

![step 06 order request product](screenshots/step-06-order-request-product.png)

![step 06 order request review](screenshots/step-06-order-request-review.png)

![step 06 order request submitted](screenshots/step-06-order-request-submitted.png)

**Video recording:**

[▶ Watch step recording](videos/step-06-order-request-submitted.webm)

---

## Database Validations

The following SQL queries ran against the application database after the Playwright scenarios completed. Each query asserts a specific condition that proves the feature under test persisted its data correctly.

### Ryan relationship now active — ✅ PASS

**Assertion:** Ryan's representation relationship should be active after manufacturer approval

```sql
SELECT id, status, active, responded_at, responded_by_user_id
      FROM organization_representation_relationships
      WHERE id = $1
```

| id | status | active | responded_at | responded_by_user_id |
| --- | --- | --- | --- | --- |
| 95d6e7f8-a9b0-1234-9012-345678901234 | active | true | 2026-04-23T03:44:15.773Z | d4e5f6a7-b8c9-0123-def1-234567890123 |

### Bob relationship still active (control) — ✅ PASS

**Assertion:** Bob's relationship should remain `active = true` (the column the certification gate actually reads) and be unaffected by Ryan's approval. The `status` string in this row is informational only and may read `proposed_pending_onboarding` from the seed data.

```sql
SELECT id, status, active
      FROM organization_representation_relationships
      WHERE id = $1
```

| id | status | active |
| --- | --- | --- |
| 84c5d6e7-f8a9-0123-8901-234567890123 | proposed_pending_onboarding | true |

### Status change history recorded — ✅ PASS

**Assertion:** Status change to "active" should be recorded in history table

```sql
SELECT id, to_status, from_status, changed_by_user_id, created_at
      FROM organization_representation_request_status_changes
      WHERE relationship_id = $1
        AND created_at > NOW() - INTERVAL '30 minutes'
      ORDER BY created_at DESC
      LIMIT 5
```

| id | to_status | from_status | changed_by_user_id | created_at |
| --- | --- | --- | --- | --- |
| 019db870-399e-7a4f-84a9-4f518efc6f49 | active | proposed | d4e5f6a7-b8c9-0123-def1-234567890123 | 2026-04-23T03:44:15.744Z |

### Bill-only order created by Ryan after certification — ✅ PASS

**Assertion:** At least one bill-only order should have been created by Ryan after being certified

```sql
SELECT bo.id, bo.order_number, bo.status, bo.created_at, bo.created_by_user_id
      FROM billing_orders bo
      WHERE bo.created_by_user_id = $1
        AND bo.created_at > NOW() - INTERVAL '30 minutes'
      ORDER BY bo.created_at DESC
      LIMIT 5
```

| id | order_number | status | created_at | created_by_user_id |
| --- | --- | --- | --- | --- |
| 019db870-bc20-789f-a38d-55a1432563ae | BO-1 | submitted | 2026-04-23T03:44:49.158Z | 28c9d0e1-f2a3-4567-2345-678901234567 |

### Order request created by Ryan after certification — ✅ PASS

**Assertion:** A standard order request should have been persisted by Ryan after certification (Step 6) — tagged with the URS-055 notes marker

```sql
SELECT id, request_number, order_type, status, sales_account_id, notes, created_at
      FROM order_requests
      WHERE requested_by_user_id = $1
        AND notes LIKE $2
        AND created_at > NOW() - INTERVAL '30 minutes'
      ORDER BY created_at DESC
      LIMIT 5
```

| id | request_number | order_type | status | sales_account_id | notes | created_at |
| --- | --- | --- | --- | --- | --- | --- |
| 019db871-3336-7dc9-bd5b-28e6e1bc4387 | OR-2 | consignment | submitted | fea7b8c9-d0e1-2345-0123-456789012345 | URS-055: post-certification order request | 2026-04-23T03:45:19.655Z |

### Audit trail for representative approval — ✅ PASS

**Assertion:** Audit/decision events should exist referencing Ryan after the approval action

```sql
SELECT ae.id, ae.event_type, ae.action, ae.created_at, ae.user_id, ae.object_id,
        substring(ae.payload::text, 1, 500) as payload_preview
      FROM audit_events ae
      WHERE ae.created_at > NOW() - INTERVAL '30 minutes'
        AND (ae.object_id = $1 OR ae.object_id = $2)
      ORDER BY ae.created_at DESC
      LIMIT 10
```

| id | event_type | action | created_at | user_id | object_id | payload_preview |
| --- | --- | --- | --- | --- | --- | --- |
| 019db870-39b0-7bc3-b69d-4076f39563f4 | transactional_email | rep_created | 2026-04-23T03:44:15.804Z | NULL | 95d6e7f8-a9b0-1234-9012-345678901234 | {"to": ["ryan.delauintana@stellartech.com"], "s3Path": "email-audit/b2c3d4e5-f6a7-8901-bcde-f12345678901/019db870-39b0-7bc3-b69d-4076f39563f4/", "subject": "Representative Account Approved - ZuriMED", "messageId": "dev-console-log", "relatedEntityType": "organization_representation_relationship"} |
| 019db870-399f-770b-84a3-365054e1902b | user_log | rep_onboarding_request_approved | 2026-04-23T03:44:15.781Z | d4e5f6a7-b8c9-0123-def1-234567890123 | 95d6e7f8-a9b0-1234-9012-345678901234 | {"userId": "28c9d0e1-f2a3-4567-2345-678901234567", "userName": "Ryan Delauintana", "userEmail": "ryan.delauintana@stellartech.com", "distributorOrganizationId": "b2c3d4e5-f6a7-8901-bcde-f12345678901", "manufacturerOrganizationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"} |

## Audit & Email Assertion Ledger

Per-declaration outcome of every `expectedAuditActions` and `expectedEmailTemplates` entry written into the orchestrator. Missing evidence here is a real test failure, not a soft warning.

### Audit Action Assertions

Each row asserts that a declared `expectedAuditActions` entry produced a matching row in `audit_events`. A ❌ flips overall status to FAIL — the declaration is real proof, not just an annotation.

| Step | Expected Audit Action | Found |
|------|-----------------------|-------|
| Step 4: Manufacturer approval | `user_log:rep_onboarding_request_approved` | ✅ |

## Audit Log Events

Every row written to `audit_events` while this test was running (scoped to the demo organizations). Provides compliance evidence that user actions are traced end-to-end (URS-003).

**Capture window start:** 2026-04-23T03:43:29.845Z

<details><summary>Query used to capture events</summary>

```sql
SELECT
    ae.created_at,
    ae.event_type,
    ae.action,
    ae.user_id,
    u.email AS user_email,
    ae.organization_id,
    o.name AS organization_name,
    ae.object_id,
    ae.secondary_object_id,
    ae.payload,
    ae.route,
    ae.trace_id
  FROM audit_events ae
  LEFT JOIN users u ON u.id = ae.user_id
  LEFT JOIN organizations o ON o.id = ae.organization_id
  WHERE ae.created_at >= $1
    AND ae.organization_id = ANY($2::uuid[])
  ORDER BY ae.created_at ASC
```
</details>

11 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-04-23 03:43:33Z | user_log | user:login | ryan.delauintana@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:43:46Z | user_log | user:login | ryan.delauintana@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:43:56Z | user_log | user:login | bob.kauffman@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:44:05Z | user_log | user:login | mark.manufacturer@zurimed.com | ZuriMED | — | — |  |
| 2026-04-23 03:44:15Z | user_log | rep_onboarding_request_approved | mark.manufacturer@zurimed.com | ZuriMED | 95d6e7f8-a9b0-1234-9012-345678901234 | — |  |
| 2026-04-23 03:44:15Z | transactional_email | rep_created | — | StellarTech Medical Solutions | 95d6e7f8-a9b0-1234-9012-345678901234 | — |  |
| 2026-04-23 03:44:23Z | user_log | user:login | ryan.delauintana@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:44:49Z | decision | bill_only_order.enqueue_upload_classification | ryan.delauintana@stellartech.com | ZuriMED | 019db870-bc20-789f-a38d-55a1432563ae | no | No uploaded PO documents |
| 2026-04-23 03:44:50Z | transactional_email | new_bill_only | — | StellarTech Medical Solutions | 019db870-bc20-789f-a38d-55a1432563ae | — |  |
| 2026-04-23 03:44:56Z | user_log | user:login | ryan.delauintana@stellartech.com | StellarTech Medical Solutions | — | — |  |
| 2026-04-23 03:45:19Z | decision | order_request_created | ryan.delauintana@stellartech.com | ZuriMED | 019db871-3336-7dc9-bd5b-28e6e1bc4387 | yes | Order request OR-2 created (importSource=manual) |

## Email Evidence

2 notification email(s) were captured during this test run. Each email is rendered as a screenshot for compliance review.

### 1. Representative Account Approved - ZuriMED

**Template:** `Representative_Account_Approved_-_ZuriMED`

![Representative Account Approved - ZuriMED](screenshots/emails/2026-04-23T03-44-15-788Z-Representative_Account_Approved_-_ZuriMED.png)

### 2. New Bill-Only Order - 4/22/2026 - ZuriMED BO-1

**Template:** `New_Bill-Only_Order_-_4_22_2026_-_ZuriMED_BO-1`

![New Bill-Only Order - 4/22/2026 - ZuriMED BO-1](screenshots/emails/2026-04-23T03-44-50-446Z-New_Bill-Only_Order_-_4_22_2026_-_ZuriMED_BO-1.png)
