# App Store Hybrid Batch Upload Design

Date: 2026-04-23

## Goal

Turn `WWW/appstore` into a general-purpose batch upload and update tool for the UnionTech app store that can:

- batch process multiple apps and multiple releases from one workbook
- handle multiple packages per release across multiple architectures
- support `deb`, `uab`, and `layer`
- reuse authenticated browser sessions
- choose between API execution and browser execution per release
- preserve the proven two-stage browser update flow needed for real multi-arch updates

The end state is not a `LabelNova` one-off script. `LabelNova` is only the validated reference case that proved which platform behaviors must be modeled.

## Context

The current `appstore` tool already has:

- a workbook-driven model with `apps / releases / packages / targets`
- package inspectors
- capability sync
- API submission support

What it does not have yet is a formal browser execution path inside the main tool.

Recent live validation against the store showed:

- browser-authenticated state is reliable and should be cached
- direct OSS upload can be fragile for large packages if treated as a blind raw-upload problem
- the store UI enforces platform rules that are easier to satisfy through the real page flow
- a two-stage save flow is more reliable than trying to configure multiple newly uploaded rows in a single page lifecycle

The specific live proof case was `LabelNova`, where:

- `arm64` had to be saved under `社区版V23`
- `loong64` had to be saved under `社区版V25`
- saving `arm64` first, returning to the list, reopening, then saving `loong64`, reopening again, and only then submitting produced a successful `审核中` result

That behavior must now become part of the formal tool design.

## Goals

- Keep the workbook-driven batch model as the top-level interface.
- Add a formal browser-backed execution path to the main CLI.
- Reuse persistent authenticated browser session state across runs.
- Preserve API-based capability sync, metadata lookup, and validation where they are stable.
- Add a platform-strategy layer that can express architecture and system-line constraints discovered from the real store behavior.
- Support release-level execution routing:
  - `api`
  - `browser`
  - `auto`
- Produce durable reports and browser artifacts for every batch run.

## Non-Goals

- Removing the existing API execution path
- Making every browser interaction fully generic on day one
- Solving every possible store UI layout variant immediately
- Supporting mixed `deb` and `linglong` package families in one release
- Replacing workbook input with a different manifest format

## Architecture

The tool will become a hybrid batch engine with five major layers.

### 1. Manifest and Validation Layer

The existing workbook schema remains the source of truth:

- `apps`
- `releases`
- `packages`
- `targets`

Validation remains grouped by `(app_key, release_key)`. The release group is the unit of execution.

### 2. Platform Capability and Policy Layer

The tool keeps using authenticated capability sync to obtain store-native system lines and baselines.

On top of that, add a policy layer that captures platform rules not fully expressed by the raw capability payload. Examples:

- `loong64` releases may require a V25 system line
- `arm64` can target V23 in the proven Debian path

This layer is not app-specific. It represents store behavior and should be reusable for any app.

### 3. Session and Browser Runtime Layer

Add a formal session store under:

- `appstore/cache/session-state/<account>.json`

It persists:

- cookies
- localStorage
- sessionStorage
- user agent
- last verification timestamp

The browser runtime is responsible for:

- launching headless or headed browser mode
- restoring session state
- verifying whether the session is still authenticated
- falling back to login only when needed
- saving refreshed session state back to the cache

Passwords are never stored in the cache.

### 4. Hybrid Execution Layer

Each release group executes in one of three modes:

- `api`
- `browser`
- `auto`

#### `api`

Use the existing API path:

- app lookup
- file upload
- payload construction
- submission

#### `browser`

Use the real page flow:

- navigate to the target app
- enter update/edit flow
- upload packages through the page
- configure system versions through the page
- save intermediate states as needed
- submit through the page

#### `auto`

Choose the safest path for the release:

- prefer API for simple validated cases that do not need browser-specific behaviors
- switch to browser when:
  - the package family or platform policy says browser is required
  - the release contains multi-package update sequences that are proven flaky through direct API-only behavior
  - the user explicitly wants the most platform-faithful route

The first concrete `auto` policy should route the proven `deb` multi-arch update pattern through the browser path.

### 5. Reporting and Artifact Layer

Every run writes:

- `report.json`
- `report.xlsx`

Browser executions additionally write:

- screenshots
- selected DOM snapshots
- sanitized request/response traces
- execution summary

Output remains under timestamped directories in `appstore/output/`.

## Browser Execution Model

The browser path must be modeled as reusable actions plus a small orchestrator.

### Reusable page actions

Examples:

- restore session and verify login
- locate app by `app_id` or package name
- open update/edit page
- upload a package file into the active file input
- locate a package row by package metadata
- open system version management for a package row
- choose system line and baseline values
- save the dialog
- save the page
- submit for review
- verify final status from the list page

### Release orchestration

The release runner composes those actions for grouped packages.

The first required orchestration pattern is the two-stage save flow:

1. open release update page
2. upload and configure the first package group
3. save and return
4. reopen update page
5. verify persisted state
6. upload and configure the next package group
7. save and return
8. reopen update page
9. verify all rows
10. submit

This pattern exists because the real portal behaved reliably under staged saves and unreliably under a single-page multi-row configuration attempt.

The implementation must make the staging behavior configurable by policy instead of hard-coding `LabelNova`.

## CLI Design

Keep `python3 -m appstore.upload_batch` as the only entrypoint.

Add or extend arguments to support hybrid execution:

- `upload <workbook>`
- `--mode auto|api|browser`
- `--headless`
- `--app-id <id>` as an optional override for targeted runs
- `--rows ...` to scope work to specific package or release rows
- `--session-cache-dir ...`
- `--artifact-dir ...`

`validate` and `sync-capabilities` remain non-browser commands.

## Data and Policy Model

The release record should gain an execution preference field if absent, such as:

- `execution_mode`

Allowed values:

- empty, meaning use CLI default
- `api`
- `browser`
- `auto`

The effective mode is resolved in this order:

1. CLI override
2. release-level value
3. tool default

Platform policy evaluation then refines `auto`.

## Error Handling

### Authentication failure

- invalidate cached session
- retry login once
- if still unauthenticated, fail the release and preserve artifacts

### Browser page drift

- fail fast
- save screenshot, HTML snapshot, and step marker
- do not continue clicking uncertain controls

### Upload failure

- preserve browser and trace artifacts
- mark the specific release group as failed
- continue to later releases unless the user requested fail-fast

### Submit failure

- capture final response and visible page state
- do not assume retry safety without returning to a known page state

## Testing Strategy

### Unit tests

- execution-mode resolution
- platform policy decisions
- staged browser plan generation for grouped packages
- session cache read/write/invalidate behavior
- artifact path generation

### Integration-style tests with fakes

- browser runner using fake page adapters
- release grouping to browser action sequences
- failure handling and artifact/report generation

### Existing tests

The current API-driven tests remain and should continue to pass. Browser support is additive.

## Files

Expected file changes:

- Modify: `appstore/upload_batch.py`
- Modify: `appstore/appstore_client.py`
- Modify: `appstore/submission.py`
- Create: `appstore/browser_session.py`
- Create: `appstore/browser_runtime.py`
- Create: `appstore/browser_flow.py`
- Create: `appstore/browser_submission.py`
- Create: `appstore/platform_policy.py`
- Modify: `appstore/tests/test_upload_batch.py`
- Create: `appstore/tests/test_browser_session.py`
- Create: `appstore/tests/test_browser_submission.py`
- Create or modify tests for platform policy behavior

## Success Criteria

The work is complete when:

- the main `appstore` CLI can execute a release in `browser` or `auto` mode
- session state is reused across runs
- the formal tool can express the proven staged multi-arch update behavior
- reports and browser artifacts are written for browser runs
- existing API workflows still work
- the new behavior is covered by automated tests
