# LabelNova Browser Submission Design

Date: 2026-04-22

## Summary

This design changes the app store upload strategy for `LabelNova` from "reconstruct the platform API by hand" to a hybrid browser-driven workflow:

- The primary execution path uses a headless browser to perform the real upload and submission flow inside the UnionTech developer portal.
- The secondary path captures the real network traffic from that browser session so the team can understand and later stabilize the underlying API behavior.
- Login state is cached on disk and reused across runs instead of being discarded after every upload attempt.

Phase 1 is intentionally narrow. It only targets the existing `LabelNova` app and only aims to update the `arm64` and `loong64` Debian packages under the same app record that already contains the `x86` package. Once that path is proven, Phase 2 will extract a general framework from the working flow.

## Goals

- Successfully submit `LabelNova` `arm64` and `loong64` packages through the real UnionTech app store web flow.
- Persist and reuse login state between runs.
- Capture the real request and response sequence for package upload, system version selection, and final submission.
- Leave behind enough artifacts to debug failures without repeating blind trial-and-error.
- Keep the new work isolated so the current `upload_batch` path is not replaced before the browser-driven path is validated.

## Non-Goals

- Generalize the solution for every app or every package family in Phase 1.
- Replace the existing batch uploader immediately.
- Automatically clean historical package rows or modify the existing `x86` package configuration.
- Solve all app store page variations in the first pass.
- Fully automate recovery from every possible mid-flow UI failure.

## Constraints

- The platform behavior is partially encoded in its front-end and has proven unstable when reverse-engineered only through direct API calls.
- The existing app store account should not require interactive re-login on every run.
- Sensitive state must not be written to the repository or to committed files.
- Debug output must be useful but sanitized enough to avoid leaking long-lived credentials or signed upload URLs.

## Phase 1 Scope

Phase 1 implements a `LabelNova`-specific browser runner with these fixed assumptions:

- app identity: existing `LabelNova` app
- target app id: `1096227`
- package family: `deb`
- target packages:
  - `labelnova_1.0.4-1_arm64.deb`
  - `labelnova_1.0.4-1_loong64.deb`
- initial system target:
  - system line `11`
  - baseline `2300`

If Phase 1 succeeds, the captured traces and browser flow will become the basis for a general framework in Phase 2.

## Architecture

Phase 1 introduces five focused modules.

### 1. Session Store

Purpose: persist and restore browser-authenticated state.

Responsibilities:

- Save and load:
  - cookies
  - localStorage
  - sessionStorage
  - user agent
  - last verification timestamp
- Keep one cache file per account under:
  - `appstore/cache/session-state/<account>.json`
- Provide:
  - `load(account)`
  - `save(account, state)`
  - `invalidate(account)`

Rules:

- Passwords are never cached.
- Cache files are runtime artifacts, not committed repository data.
- Any detected authentication failure invalidates the cached state and forces a fresh login.

### 2. Browser Runtime

Purpose: own the browser lifecycle and authenticated page bootstrap.

Responsibilities:

- Launch headless or headed browser mode.
- Restore cached state before opening protected pages.
- Verify whether the session is still valid.
- Fall back to interactive login when the restored state is invalid.
- Refresh the cached session after a successful login.

Validation rules:

- "Logged in" is determined by actual portal state, not just by the presence of cookies.
- Verification must check a page or API that clearly proves authenticated developer access.

### 3. Network Recorder

Purpose: capture the real platform traffic for diagnosis and later API alignment.

Responsibilities:

- Listen to browser request and response events.
- Record only relevant traffic, especially:
  - `store-file/upload/begin`
  - `store-file/upload/end`
  - `store-dev-app/app`
  - app detail or edit requests
  - system version management requests
- Write structured trace output to:
  - `appstore/output/debug-traces/<timestamp>/`

Artifacts:

- `requests.jsonl`
- `responses.jsonl`
- `summary.json`

Sanitization rules:

- redact token-like headers
- redact cookies
- redact signed OSS query parameters
- preserve enough structure to compare payload shapes and status codes

### 4. LabelNova Submit Flow

Purpose: encode the real page interactions for the single app under test.

Responsibilities:

- Navigate to the correct app.
- Enter the update or edit path for package management.
- Upload `arm64` and `loong64` packages.
- Configure system versions for those package rows.
- Submit the updated app for review.

This module is intentionally app-specific in Phase 1. It should be written in a way that can later be split into generic page actions and per-app orchestration, but it does not need to be generic yet.

### 5. Artifact Writer

Purpose: preserve evidence from every run.

Each run writes a timestamped artifact directory containing:

- step screenshots
- selected DOM snapshots
- trace summaries
- final status summary
- failure marker with the last completed step

Failure artifacts must be kept even when the run aborts early.

## Browser Flow

The Phase 1 browser flow for `LabelNova` is:

1. Open `https://appstore-dev.uniontech.com/#/index`
2. Restore cached session state if available
3. Verify login state
4. If invalid, perform login and refresh cache
5. Navigate to the existing `LabelNova` app
   - prefer app-id-based routing if stable
   - otherwise use app list search by `pkg_name=labelnova`
6. Validate that the page matches the intended app
   - app name is `LabelNova`
   - package name is `labelnova`
7. Enter the package update or edit flow
8. Upload `arm64` package
9. Wait for the corresponding package row to appear and validate:
   - `pkg_name = labelnova`
   - `pkg_version = 1.0.4-1`
   - architecture resolves to `ARM`
10. Upload `loong64` package
11. Wait for the corresponding package row to appear and validate:
   - `pkg_name = labelnova`
   - `pkg_version = 1.0.4-1`
   - architecture resolves to `loong64`
12. For each newly uploaded package row, open system version management
13. Select:
   - system line `11`
   - baseline `2300`
14. Save the system version selection
15. Re-validate the package row state on return
16. Submit the app update
17. Capture the final request, response, page status, toast text, and terminal page state

Success is defined as a platform-visible reviewed or pending-review state, such as "审核中", or another clearly equivalent state from the portal.

## Selector Strategy

Selectors must be resilient enough for repeated use but not over-engineered in Phase 1.

Priority order:

1. stable route or route parameters
2. table row matching by app/package content
3. candidate button labels
4. nearby DOM context when text-only matching is too weak

Rules:

- Every destructive or high-impact click must be preceded by a content assertion.
- Every major transition must produce a screenshot and, when helpful, an HTML snapshot.
- If the expected page or row cannot be proven, the run stops immediately.

## Failure Handling

Phase 1 uses fail-fast behavior with rich evidence capture.

### Authentication Failure

- Invalidate cached session.
- Retry through the login path once.
- If authentication still fails, stop and preserve artifacts.

### Page Structure Drift

- Stop at the first unresolved selector or assertion failure.
- Save screenshot, DOM snapshot, and current URL.
- Preserve trace summary for the requests already observed.

### Package Upload Failure

- Preserve upload begin/end traffic and any OSS upload traffic summaries.
- Do not blindly keep clicking the page.
- Stop after the current package failure is confirmed.

### Submission Failure

- Record the final submission request and response body.
- Preserve page state after the failure.
- Do not automatically retry final submission in the same run.

## Session Cache Policy

Session cache is a first-class runtime feature.

Storage location:

- `appstore/cache/session-state/`

Policy:

- cache per account
- restore first, verify second
- invalidate on proven auth failure
- refresh cache after successful login
- avoid rewriting cache unnecessarily when the verified session remains valid

The cache exists to reduce repeated manual logins and to make debugging runs faster and more stable.

## Trace Output Policy

Trace output is required for every Phase 1 run.

Storage location:

- `appstore/output/debug-traces/<timestamp>/`

Minimum contents:

- request method
- request URL
- redacted headers
- request payload summary
- response status
- response payload summary
- step label that triggered the request when that context is available

These traces are not only debug artifacts. They are the raw input for Phase 2 API normalization work.

## Implementation Boundary With Existing Tools

The existing `appstore.upload_batch` path remains in place but is no longer the only path used for real submissions.

Phase 1 rules:

- do not replace the current batch uploader yet
- do not force the browser flow through the existing workbook schema
- do not block current API experiments from continuing
- keep the new browser runner isolated enough that it can be removed or generalized cleanly

## Phase 2 Direction

Only after the `LabelNova` browser runner is proven should the project extract a general framework.

Phase 2 will likely split the Phase 1 implementation into:

- reusable session cache
- reusable browser runtime
- reusable network recorder
- reusable page primitives
- a generalized app submission orchestrator

The Phase 2 design is intentionally deferred until the Phase 1 flow is proven against the live portal.

## Testing Strategy

Phase 1 needs both code-level and live-flow verification.

Code-level:

- session cache serialization and invalidation tests
- trace redaction tests
- selector helper tests where practical
- browser flow unit tests for deterministic helpers only

Live-flow:

- manual or semi-automated validation against the real app store portal
- verify that cached login can be reused on the second run
- verify that artifacts are produced on both success and failure
- verify that the trace output captures the final submission request path

## Risks

- The portal may change page structure without notice.
- The upload flow may rely on hidden component state that is harder to trigger outside the exact page sequence.
- Cached sessions may expire or become invalid in non-obvious ways.
- Browser timing and page readiness may differ between runs.

These risks are acceptable in Phase 1 because the design prioritizes evidence capture and a narrow app-specific target over broad abstraction.
