PHPUnit 11.5.57 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.6
Configuration: /workspace/scratch/a621dd1a9f75/primelink-r5/laravel/phpunit.xml

...............................................................  63 / 119 ( 52%)
........................................................        119 / 119 (100%)

Time: 00:03.728, Memory: 66.50 MB

Example (Tests\Feature\Example)
 ✔ Guest is redirected to login

Example (Tests\Unit\Example)
 ✔ That true is true

Installer (Tests\Unit\Installer)
 ✔ Private key created without cli and stable
 ✔ Unlock throttles incorrect keys
 ✔ Existing environment is never overwritten
 ✔ Empty environment is also preserved
 ✔ Validation normalises domain email and custom database port
 ✔ Invalid origins dsn injection and weak passwords rejected
 ✔ Review credentials are authenticated encrypted
 ✔ Dotenv password punctuation round trip
 ✔ Database rejection never writes or migrates
 ✔ Success locks and keeps configuration on retry
 ✔ Interrupted migration preserves environment and blocks retry
 ✔ Concurrent setup rejected before database probe
 ✔ Preflight requires real https and correct document root

Primelink (Tests\Feature\Primelink)
 ✔ Customer isolation and no board routes
 ✔ Board has aggregates not customer records
 ✔ Reseller cross partner scope
 ✔ Internal notes never enter customer portal
 ✔ Staff permissions deny board and allow assigned module
 ✔ Signed store events are idempotent and pending is not paid
 ✔ Store signature rejected and verified event settles once
 ✔ Payment amount mismatch never credits
 ✔ Paystack requires signature and independent verification
 ✔ Commission gates hold and single payout
 ✔ Csv preview commit and duplicate protection
 ✔ Unsigned social feed rejected and signed feed deduplicated
 ✔ Sso is one time and cannot take over admin
 ✔ Schedule sast month end and snapshot is immutable
 ✔ All primary admin views render
 ✔ Board pdf generation and download authorization
 ✔ Full refund reverses unpaid commission and recovers paid fee
 ✔ Customer tabs and reseller tabs render with scoped data
 ✔ Exports do not expose other customers or board data
 ✔ Disabled user cannot reuse existing session
 ✔ Projection example and permissions
 ✔ Catalog sync retains local commission rate
 ✔ Refund recovery offsets next payout and cancellation restores it
 ✔ A checkout return never settles an order
 ✔ Activation requires paid delivery and verified rica
 ✔ Product management renders imported products

R2 (Tests\Feature\R2)
 ✔ Invoice gross tax and issue idempotency
 ✔ Invoice tax requires supplier registration
 ✔ Invoice customer scope draft and board boundaries
 ✔ Partial payments credits and unique bank references
 ✔ Credits and manual payments cannot overallocate
 ✔ Pending gateway checkout blocks credit changes
 ✔ Invoice gateway receipt is idempotent and excess goes to review
 ✔ Invoice paystack webhook uses independent verification
 ✔ Subscription month end and activation once no wordpress duplicates
 ✔ Task owner scope and first completion evidence
 ✔ Private files owner visibility and review authority
 ✔ Upload rejects executable content
 ✔ Recordings require audio and recorded consent
 ✔ Device assignment scope masking and return
 ✔ Port request scope sequence and rica gate
 ✔ New admin views render and staff permissions apply
 ✔ Invoice pdf and immutable supplier snapshot
 ✔ Paused subscription resume skips the paused period
 ✔ Gateway transaction cannot pay both order and invoice
 ✔ Real audio recording consent upload and playback
 ✔ Finance reverification and reconciliation access
 ✔ Populated billing and document views render

R3 (Tests\Feature\R3)
 ✔ Totp rfc6238 sha1 vectors
 ✔ Authenticator secret encrypted and codes single use
 ✔ Password login requires mfa before authentication
 ✔ Existing session and required roles cannot skip mfa
 ✔ Mfa setup recovery and policy require own credentials
 ✔ Campaign requires evidenced channel permission
 ✔ Consent withdrawal after review skips submission
 ✔ Email submission idempotency and unsubscribe
 ✔ Campaign confirmation and portal boundaries
 ✔ Workflow requires approved host and signed acknowledgement
 ✔ Workflow failure is review without automatic retry
 ✔ Workflow host cannot be selected without server allowlist
 ✔ Openai only receives numeric scenario and stores plain advice
 ✔ Provider secrets are encrypted and never echoed
 ✔ Partner tools are scoped and agreement ack is owner only
 ✔ Partner fee snapshot and campaign attribution survive rate changes
 ✔ Partner link signed validation and disabled capture
 ✔ Campaign deduplicates contacts and cancelled jobs never send
 ✔ Password reset invalidates an existing session
 ✔ Old mfa enrolment marker cannot verify a new secret

R5 (Tests\Feature\R5)
 ✔ Calendar sast storage and overlap guard
 ✔ Adjacent appointments are allowed
 ✔ Staff calendar is scoped and cannot assign other staff
 ✔ Ineligible customer board and disabled owners are rejected
 ✔ Reschedule records audit and respects conflicts
 ✔ Future completion and early no show are rejected
 ✔ Completion is single record and terminal state is immutable
 ✔ Activity is internal attributed and does not grant consent
 ✔ Converted lead activity appears in customer workspace only for crm
 ✔ Calendar and workspace denied to other portals
 ✔ Quote once monthly and gross tax totals
 ✔ Quote new and edit views and blank rows work
 ✔ Publish freezes buyer supplier and prevents edits
 ✔ Unpublished and withdrawn drafts are hidden from customers
 ✔ Customer quote scope private notes and pdf
 ✔ Customer can accept own quote without creating a charge
 ✔ Expired quote cannot be accepted even across sast midnight
 ✔ Acceptance requires acknowledgement and external sales reference
 ✔ Draft invoice conversion is idempotent and uses frozen buyer
 ✔ Wordpress quote blocks native invoice and sales staff cannot bill
 ✔ Revision does not change original and has no acceptance or invoice
 ✔ Board reseller and unrelated staff cannot view quotes
 ✔ Billing staff cannot publish or accept sales quote
 ✔ Quote supplier profile and vat are required before publish
 ✔ Overnight appointment carries into the next calendar week
 ✔ Lead owner picker excludes ineligible roles
 ✔ Published pdf does not use later customer contact details
 ✔ Quotation number uses south african business year

Setup (Tests\Feature\Setup)
 ✔ Setup is admin only across every action
 ✔ Setup never echoes private connection keys
 ✔ Private connection download requires password and is not cached
 ✔ Log transport cannot report a successful email test
 ✔ Explicit smtp test sends only to requesting admin
 ✔ Smtp failures do not expose provider secrets
 ✔ Heartbeat distinguishes scheduler from worker execution
 ✔ Signed wordpress handshake exposes no customer or secret data

OK (119 tests, 629 assertions)

PASS failed lead is retained for retry
PASS payload survives failed delivery
PASS backoff retry scheduled
PASS exact raw lead body signed
PASS acknowledged lead marked delivered
PASS delivered payload removed locally
PASS delivered event is not sent again
PASS exhausted delivery remains available for admin recovery
PASS campaign cookie signature verified
PASS tampered campaign cookie rejected
PASS expired campaign cookie rejected
PASS valid browser profile accepted
PASS unsafe profile field rejected: portal_url
PASS unsafe profile field rejected: bridge_secret
PASS unsafe profile field rejected: schema
PASS unsafe profile field rejected: store_id
PASS imported social secret works without wp-config edits
PASS existing wp-config constant retains precedence
PASS conflicting existing constant blocks import
19 connector assertions passed. Full WordPress/gateway staging still required.

R5 fresh installer engine with all cumulative MariaDB migrations passed. The workflow validation below used actual MariaDB 10.11.14 in an isolated QA database. No live host, WordPress or gateway was contacted. R4 browser HTTP/TLS-metadata/ownership checks are retained in the cumulative baseline. Production-host SSL and provider validation remain outstanding.
Database: 10.11.14-MariaDB-0ubuntu0.24.04.1
PASS R5 fresh browser-installer engine with all MariaDB migrations

PASS SAST appointment stored as UTC on MariaDB
PASS MariaDB overlap prevented under owner-row lock
PASS Converted lead contact history linked to customer on MariaDB
PASS Quotation stores separate integer gross amounts on MariaDB
PASS Quote-to-invoice conversion is idempotent on MariaDB
PASS Only once-off plus first month billed as a draft
PASS Prefixed invoice description fits MySQL string limits
PASS No recurring subscription or payment fabricated
PASS Quotation PDF rendered from real MariaDB records
9 R5 MariaDB workflow assertions passed.

All R5 MariaDB validation passed. No live host, WordPress or external gateway was contacted.

PHP lint: 119 files passed. Blade compilation and JavaScript syntax passed. Quotation PDF rendered and visually inspected with embedded DejaVu Sans fonts. Composer locked dependency audit passed with no vulnerability advisories.
