# Validation Report: URS-078

**Title:** Recertification required for a new certification version
**Date:** 2026-09-29T02:30:59.671Z
**Duration:** 69.7s
**Overall Status:** ✅ PASS

## User Requirement

> The system shall require recertification when a newer certification version supersedes the version a representative completed, re-engaging the per-manufacturer action block until the current version is completed, preserving the prior completion record unchanged while linking the new completion to it, and re-engaging the block per manufacturer when a new mandatory certification requirement is introduced.

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

## Environment

- **Inbox URL:** http://localhost:38449
- **Database:** localhost:41169/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 1a: Gate re-engaged for superseded version — ✅ PASS

**What this step proves:**

A representative who completed version 1 of the manufacturer's required certification opens bill-only and order-request creation after version 2 was published. The manufacturer is absent from both manufacturer pickers with a 'Certification required' notice, and the certification checklist offers the updated training form again — not an already-certified state — despite the completed version-1 record.

**Screenshots:**

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

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

![step 01 training offered again](screenshots/step-01-training-offered-again.png)

**Video recording:**

[▶ Watch step recording](videos/step-01-gate-reengaged.webm)

---

### 2. Step 1b: Trunk order requests allowed while pending — ✅ PASS

**Screenshots:**

![step 01 orders trunk allowed](screenshots/step-01-orders-trunk-allowed.png)

---

### 3. Step 2: Recompletion creates a new record — ✅ PASS

**What this step proves:**

The representative completes version 2 behind the Part 11 signing re-authentication gate, using the MAGIC LINK path: a one-time signing code is requested, read out of the email the system sent, and carried into the page through the emailed link, which verifies it and strips the code from the URL. The representative then acknowledges the updated training document (timestamped server-side), passes the knowledge check at 100%, signs, and receives a fresh certificate. The recompletion writes a NEW certification record that supersedes the version-1 record; the historical record is never modified. The manufacturer immediately reappears in the pickers.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-09-29T02:31:31.492Z → 2026-09-29T02:31:52.426Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-09-29 02:31:32Z | transactional_email | certification_signing_code | — | Vantis | — |
| 2026-09-29 02:31:33Z | certification | signing_code_verified | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:42Z | decision | forms.grade_submission | theo.larsen@corvetasurgical.com | Vantis | yes |
| 2026-09-29 02:31:46Z | certification | signing_code_consumed | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:46Z | certification | completed | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:46Z | certification | superseded | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:46Z | organization_representation | status_change | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:46Z | decision | certifications.complete_certification.mark_relationship_certified | theo.larsen@corvetasurgical.com | Vantis | yes |
| 2026-09-29 02:31:46Z | decision | certifications.complete_certification.issue_certificate | theo.larsen@corvetasurgical.com | Vantis | yes |
| 2026-09-29 02:31:46Z | user_log | rep_relationship_certified | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:47Z | certification_certificate | issued | theo.larsen@corvetasurgical.com | Vantis | — |
| 2026-09-29 02:31:47Z | certification_completion_record | issued | theo.larsen@corvetasurgical.com | Vantis | — |

**Emails triggered by this step:**

*(Evidence matched by declared name — step timing not available or no events fell in window)*

**Email 1: Your signing code for LiraLock Implant System Certification**

Template: `Your_signing_code_for_LiraLock_Implant_System_Certification`

![Your signing code for LiraLock Implant System Certification](screenshots/emails/2026-09-29T02-31-32-431Z-Your_signing_code_for_LiraLock_Implant_System_Certification.png)

**Screenshots:**

![step 02 signing code sent](screenshots/step-02-signing-code-sent.png)

![step 02 magic link verified](screenshots/step-02-magic-link-verified.png)

![step 02 doc acknowledged](screenshots/step-02-doc-acknowledged.png)

![step 02 quiz passed](screenshots/step-02-quiz-passed.png)

![step 02 signature](screenshots/step-02-signature.png)

![step 02 completed](screenshots/step-02-completed.png)

![step 02 certificate ready](screenshots/step-02-certificate-ready.png)

![step 02 gate lifted](screenshots/step-02-gate-lifted.png)

**Video recording:**

[▶ Watch step recording](videos/step-02-recompletion.webm)

---

### 4. Step 3: New requirement re-gates per manufacturer — ✅ PASS

**What this step proves:**

A second manufacturer's admin creates a certification required of all representatives. The previously active representative is demoted to pending certification for that manufacturer only: its name leaves the picker while the freshly recertified manufacturer remains selectable — the inverse of the run's starting state, proving per-manufacturer isolation of the requirement.

**Audit events generated by this step:**

*(Evidence scoped to step execution window: 2026-09-29T02:31:59.242Z → 2026-09-29T02:32:08.273Z)*

| Time | Type | Action | User | Org | Performed |
|------|------|--------|------|-----|-----------|
| 2026-09-29 02:31:59Z | checklist | checklists.create | halcyon.admin@urs078.example | Corveta Surgical Group | — |
| 2026-09-29 02:32:01Z | user_log | user:login | theo.larsen@corvetasurgical.com | Corveta Surgical Group | — |

**Screenshots:**

![step 03 create dialog](screenshots/step-03-create-dialog.png)

![step 03 cert created](screenshots/step-03-cert-created.png)

![step 03 rep regated](screenshots/step-03-rep-regated.png)

**Video recording:**

[▶ Watch step recording](videos/step-03-new-requirement.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.

### Historical version-1 record untouched by the recompletion — ✅ PASS

**Assertion:** Every column of the version-1 record is byte-identical to the setup snapshot

```sql
SELECT row_to_json(r)::text AS row FROM certification_records r WHERE r.id = $1
```

| row |
| --- |
| {"id":"ce000700-0000-4000-8000-000000000004","organization_id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","certification_id":"ce000100-0000-4000-8000-000000000001","certification_version_id":"ce000200-0000-4000-8000-000000000001","rep_user_id":"ce000001-0000-4000-8000-000000000004","requesting_organization_id":"b2c3d4e5-f6a7-8901-bcde-f12345678901","completed_at":"2025-12-03T02:23:22.269+00:00","signature_ref":"demo-signature/ce000700-0000-4000-8000-000000000004","form_submission_id":"ce000600-0000-4000-8000-000000000004","supersedes_record_id":null,"created_at":"2025-12-03T02:23:22.269+00:00","expires_at":"2027-12-03"} |

### Recompletion created a new record superseding the version-1 record — ✅ PASS

**Assertion:** Exactly two records exist: the fixture version-1 record and a new version-2 record that supersedes it, with completion timestamp, signature reference, and form submission

```sql
SELECT id, certification_version_id, supersedes_record_id,
            completed_at, signature_ref, form_submission_id
     FROM certification_records
     WHERE rep_user_id = $1 AND certification_id = $2
     ORDER BY created_at
```

| id | certification_version_id | supersedes_record_id | completed_at | signature_ref | form_submission_id |
| --- | --- | --- | --- | --- | --- |
| ce000700-0000-4000-8000-000000000004 | ce000200-0000-4000-8000-000000000001 | NULL | 2025-12-03T02:23:22.269Z | demo-signature/ce000700-0000-4000-8000-000000000004 | ce000600-0000-4000-8000-000000000004 |
| 01a0eb01-017f-7c10-8dd3-1e49694588fe | ce000200-0000-4000-8000-000000000002 | ce000700-0000-4000-8000-000000000004 | 2026-09-29T02:31:46.815Z | 01a0eb01-017f-7c10-8dd3-1e4a40d10df4 | 01a0eb00-f08d-7fb9-b480-a4606690798d |

### Part 11 signing challenge (magic-link path) verified, consumed, and linked to the new signature — ✅ PASS

**Assertion:** Exactly one consumed signing challenge exists for the recompletion: emailed, verified (magic link opened the signing window), consumed by the completion, linked to the NEW record's signature, and storing only a sha256 hash — never the raw code

```sql
SELECT ch.code_hash, ch.email_sent_at, ch.verified_at, ch.signing_window_expires_at,
            ch.consumed_at, ch.consumed_signature_id, r.signature_ref
     FROM certification_signing_challenges ch
     JOIN certification_records r
       ON r.rep_user_id = ch.user_id AND r.certification_id = ch.certification_id
      AND r.id != $3
     WHERE ch.user_id = $1 AND ch.certification_id = $2
       AND ch.consumed_at IS NOT NULL
```

| code_hash | email_sent_at | verified_at | signing_window_expires_at | consumed_at | consumed_signature_id | signature_ref |
| --- | --- | --- | --- | --- | --- | --- |
| 16852c4e9dd03e855a14f158cc931cbe9113103563fe37864402d68a10f46e43 | 2026-09-29T02:31:31.235Z | 2026-09-29T02:31:33.638Z | 2026-09-29T06:31:33.638Z | 2026-09-29T02:31:46.823Z | 01a0eb01-017f-7c10-8dd3-1e4a40d10df4 | 01a0eb01-017f-7c10-8dd3-1e4a40d10df4 |

### Status change recorded: relationship re-activated on recompletion — ✅ PASS

**Assertion:** A status-change row with reason_code certification_completed moved the relationship to active

```sql
SELECT from_status, to_status, reason_code
     FROM organization_representation_request_status_changes
     WHERE relationship_id = $1
       AND to_status = 'active' AND reason_code = 'certification_completed'
       AND created_at > NOW() - INTERVAL '2 hours'
```

| from_status | to_status | reason_code |
| --- | --- | --- |
| pending_certification | active | certification_completed |

### Completed and superseded audit events recorded for the recompletion — ✅ PASS

**Assertion:** Both a certification 'completed' and a certification 'superseded' audit event exist

```sql
SELECT action, COUNT(*)::int AS count
     FROM audit_events
     WHERE event_type = 'certification' AND action IN ('completed', 'superseded')
       AND organization_id = $1 AND user_id = $2
       AND created_at > NOW() - INTERVAL '2 hours'
     GROUP BY action
```

| action | count |
| --- | --- |
| completed | 1 |
| superseded | 1 |

### Second manufacturer's certification created with version 1 and an all-reps requirement — ✅ PASS

**Assertion:** One certification exists for the second manufacturer with version_number 1 and an active mandatory all_reps assignment

```sql
SELECT c.name, v.version_number, a.target_type, a.mandatory, a.active
     FROM certifications c
     JOIN certification_versions v ON v.certification_id = c.id
     JOIN certification_assignments a ON a.certification_id = c.id
     WHERE c.organization_id = $1
```

| name | version_number | target_type | mandatory | active |
| --- | --- | --- | --- | --- |
| Halcyon Field Safety Certification | 1 | all_reps | true | true |

### Second manufacturer's created and assigned audit events recorded — ✅ PASS

**Assertion:** Both a certification 'created' and a certification 'assigned' audit event exist

```sql
SELECT action FROM audit_events
     WHERE event_type = 'certification' AND action IN ('created', 'assigned')
       AND organization_id = $1
       AND created_at > NOW() - INTERVAL '2 hours'
```

| action |
| --- |
| assigned |
| created |

### New requirement demoted the representative to pending_certification — ✅ PASS

**Assertion:** The second-manufacturer relationship is pending_certification with a demotion status-change row (reason_code recertification_assignment)

```sql
SELECT r.status, r.active,
       (SELECT COUNT(*)::int FROM organization_representation_request_status_changes sc
        WHERE sc.relationship_id = r.id
          AND sc.to_status = 'pending_certification' AND sc.reason_code = $2
          AND sc.created_at > NOW() - INTERVAL '2 hours') AS demotion_changes
     FROM organization_representation_relationships r WHERE r.id = $1
```

| status | active | demotion_changes |
| --- | --- | --- |
| pending_certification | false | 1 |

### No completion record exists for the second manufacturer's certification — ✅ PASS

**Assertion:** The representative has no completion record for the new requirement

```sql
SELECT COUNT(*)::int AS count
     FROM certification_records
     WHERE rep_user_id = $1 AND organization_id = $2
```

| count |
| --- |
| 0 |

## 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 2: Recompletion creates a new record | `certification:signing_code_issued` | ✅ |
| Step 2: Recompletion creates a new record | `certification:signing_code_verified` | ✅ |
| Step 2: Recompletion creates a new record | `certification:signing_code_consumed` | ✅ |
| Step 2: Recompletion creates a new record | `certification:completed` | ✅ |
| Step 2: Recompletion creates a new record | `certification:superseded` | ✅ |

### Email Template Assertions

Each row asserts that a declared `expectedEmailTemplates` entry was matched (case-insensitive substring) by a captured email subject or template. A ❌ flips overall status to FAIL.

| Step | Expected Template | Found |
|------|-------------------|-------|
| Step 2: Recompletion creates a new record | `Your signing code` | ✅ |

## 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-09-29T02:30:57.812Z

<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>

18 event(s) captured:

| Time | Type | Action | User | Org | Object ID | Performed | Reason |
|------|------|--------|------|-----|-----------|-----------|--------|
| 2026-09-29 02:31:05Z | user_log | user:login | theo.larsen@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-09-29 02:31:25Z | user_log | user:login | theo.larsen@corvetasurgical.com | Corveta Surgical Group | — | — |  |
| 2026-09-29 02:31:31Z | decision | certifications.signing_challenge.send_sms | theo.larsen@corvetasurgical.com | Vantis | 01a0eb00-c46f-708c-8ed7-eebc71e00c0e | no | no_phone_channel |
| 2026-09-29 02:31:31Z | certification | signing_code_issued | theo.larsen@corvetasurgical.com | Vantis | ce000100-0000-4000-8000-000000000001 | — |  |
| 2026-09-29 02:31:32Z | transactional_email | certification_signing_code | — | Vantis | 01a0eb00-c46f-708c-8ed7-eebc71e00c0e | — |  |
| 2026-09-29 02:31:33Z | certification | signing_code_verified | theo.larsen@corvetasurgical.com | Vantis | ce000100-0000-4000-8000-000000000001 | — |  |
| 2026-09-29 02:31:42Z | decision | forms.grade_submission | theo.larsen@corvetasurgical.com | Vantis | ce000300-0000-4000-8000-000000000002 | yes | all_answers_correct |
| 2026-09-29 02:31:46Z | certification | signing_code_consumed | theo.larsen@corvetasurgical.com | Vantis | ce000100-0000-4000-8000-000000000001 | — |  |
| 2026-09-29 02:31:46Z | certification | completed | theo.larsen@corvetasurgical.com | Vantis | 01a0eb01-017f-7c10-8dd3-1e49694588fe | — |  |
| 2026-09-29 02:31:46Z | certification | superseded | theo.larsen@corvetasurgical.com | Vantis | ce000700-0000-4000-8000-000000000004 | — |  |
| 2026-09-29 02:31:46Z | organization_representation | status_change | theo.larsen@corvetasurgical.com | Vantis | ce000002-0000-4000-8000-000000000004 | — | Certification completed |
| 2026-09-29 02:31:46Z | decision | certifications.complete_certification.mark_relationship_certified | theo.larsen@corvetasurgical.com | Vantis | ce000002-0000-4000-8000-000000000004 | yes | relationship_pending_certification |
| 2026-09-29 02:31:46Z | decision | certifications.complete_certification.issue_certificate | theo.larsen@corvetasurgical.com | Vantis | 01a0eb01-017f-7c10-8dd3-1e49694588fe | yes | quiz_backed_completion |
| 2026-09-29 02:31:46Z | user_log | rep_relationship_certified | theo.larsen@corvetasurgical.com | Vantis | — | — | Certification completed |
| 2026-09-29 02:31:47Z | certification_certificate | issued | theo.larsen@corvetasurgical.com | Vantis | 01a0eb01-01da-78a6-b524-f038348c0e19 | — |  |
| 2026-09-29 02:31:47Z | certification_completion_record | issued | theo.larsen@corvetasurgical.com | Vantis | 01a0eb01-01e3-7782-9baa-2d36e2a55b13 | — |  |
| 2026-09-29 02:31:59Z | checklist | checklists.create | halcyon.admin@urs078.example | Corveta Surgical Group | 01a0eb01-349e-701c-b1ca-fa5a165ebaaa | — |  |
| 2026-09-29 02:32:01Z | user_log | user:login | theo.larsen@corvetasurgical.com | Corveta Surgical Group | — | — |  |

## Email Evidence

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

### 1. Your signing code for LiraLock Implant System Certification

**Template:** `Your_signing_code_for_LiraLock_Implant_System_Certification`

![Your signing code for LiraLock Implant System Certification](screenshots/emails/2026-09-29T02-31-32-431Z-Your_signing_code_for_LiraLock_Implant_System_Certification.png)

## Additional Video Evidence

The following screencast recordings were captured but could not be matched to a specific test step. Step-matched recordings appear inline in their respective step sections above.

- [videos/step-03-rep-regated.webm](videos/step-03-rep-regated.webm)
