# Phase 9 - Desktop QA + Security + Regression

Status: completed  
Date: 2026-04-19  
Target: `WepAppOpusApiDesktop`

## 1) Objective

Harden Desktop runtime security and lock regression coverage for live/token flows after phase 8 caching.

## 2) Security hardening

## 2.1 Window navigation guards (Electron main)

Added:
1. `main/security/window-guards.js`

Integrated in:
1. `main/main.js`

Guards applied:
1. deny all `window.open`
2. only allow safe external protocols (`http`, `https`, `mailto`, `tel`) via `shell.openExternal`
3. block cross-origin `will-navigate`
4. block `will-attach-webview`
5. deny all permission requests from renderer session

BrowserWindow security flags now explicitly set:
1. `webSecurity: true`
2. `allowRunningInsecureContent: false`
3. `webviewTag: false`

## 2.2 Live payload validation limits

Updated `main/live/live-service.js` with strict validation:
1. date format validation (`YYYY-MM-DD`)
2. `until >= since`
3. max date window (`LIVE_MAX_DATE_RANGE_DAYS`, default 365)
4. max inline token sources (`LIVE_MAX_INLINE_TOKEN_SOURCES`, default 20)
5. max account selections (`LIVE_MAX_ACCOUNT_SELECTIONS`, default 200)
6. max campaign query length (`LIVE_MAX_CAMPAIGN_QUERY_LENGTH`, default 120)

New error codes surfaced through contract:
1. `DATE_RANGE_TOO_LARGE`
2. `TOO_MANY_TOKEN_SOURCES`
3. `TOO_MANY_ACCOUNT_SELECTIONS`
4. `CAMPAIGN_QUERY_TOO_LONG`

## 3) Regression coverage

New tests:
1. `tests/security/window-guards.test.js`
2. `tests/live/live-cache.test.js` (phase 8 cache module)

Expanded tests:
1. `tests/live/live-service.test.js`
   - date range hard limit
   - token source hard limit
   - campaign query length limit
   - dashboard cache-hit regression check

## 4) Verification

Commands executed:
1. `npm run lint`
2. `npm run test`
3. `npm run build:renderer`
4. `npm run build:win`

Result:
1. all checks passed
2. installer artifacts generated in `WepAppOpusApiDesktop/release`

## 5) Residual risk

1. production code-signing is still not configured (`signtool` skipped), so SmartScreen trust is unchanged
2. UI-level e2e regression for `/live` interactions is not automated yet (current coverage is module/unit level)
