merge: integrate extension auto-update

This commit is contained in:
inman committed 2026-09-03 15:57:58 +08:00
commit 322475860a
40 files changed
+3208 -76

No files matched your search

@@ -0,0 +1,70 @@
# Task: Add adaptive ERP readiness wait and assess extension auto-update
## Identity
- Task ID: 20260903-adaptive-wait-auto-update-7b3e9a2c
- Mode: Feature
- Branch: codex/20260903-adaptive-wait-auto-update-7b3e9a2c-adaptive-wait-auto-update
- Worktree: /Users/inmanx/Documents/lwltAPI-adaptive-wait-auto-update-7b3e9a2c
- Base commit: 69ea6d25178d75abf8d7fd728bd31c61764caa7d
- Owner: codex
- Status: Ready for Integration
## Scope
- Make `shared_plan_create` wait adaptively for the ERP scatter-plan list add button instead of failing immediately while the list document is still rendering.
- Preserve a zero-delay fast path: check immediately, then poll the current main-frame document at a short interval only while the button is absent, with one bounded pre-write timeout.
- Add focused regression coverage and publish a synchronized Chrome extension `0.5.166` source/package baseline, including the platform minimum version, mappings, release gate, archive, and release manifest.
- Assess a server-published, client-auto-updated extension channel against Chrome's current supported distribution mechanisms; do not invent an extension ID/signing key or ship a partially operable self-update channel before the managed-device/Web Store choice is known.
## Intent And Constraints
- The supplied production log and retry behavior identify a pre-write page-readiness race: script injection completed, but `NewBuildB` was queried before the same-path ERP frame finished rendering.
- Reacquire `Iframe_Home.contentDocument` during each readiness probe so a stale same-path `Document` object cannot satisfy navigation; proceed as soon as a connected, enabled add button exists.
- Keep the wait entirely before the click and before any ERP write. Do not add automatic business-operation retry or weaken any existing product, form, preflight, write, or requery gate.
- Follow `RELEASE-001`: extension source, version strings, platform minimum, mappings, tests, ZIP, archived superseded package/manifest, and `dist/release-manifest.json` must remain synchronized.
- Chrome Manifest V3 remote-code restrictions remain intact. True silent updates must use Chrome Web Store distribution or a same-key signed CRX installed through supported enterprise policy; the existing unpacked ZIP workflow cannot silently replace itself.
- Do not access ERP, reload/install extensions, deploy services, mutate tasks/runtime data, inspect secrets, create signing keys, or publish externally in this Feature task.
- Other registered local tasks do not semantically conflict. The only related release-export task was read-only, and the main checkout remains owned by a separate migration/restart task.
## Outcome
- Added an adaptive pre-write readiness gate for `shared_plan_create`: the extension checks the current ERP list document immediately, then reacquires `Iframe_Home.contentDocument` every 100 ms only while the connected, enabled `NewBuildB` button is absent, with a 15-second total timeout.
- `createSplitParentLive` now clicks the exact button/document returned by that gate. A timeout remains a fail-closed pre-write blocker and does not retry the business operation or weaken any existing form, save, or requery evidence gate.
- Added a static regression that proves the zero-delay fast path, current-frame reacquisition, connected/enabled checks, bounded polling, and removal of the former immediate one-shot button query.
- Synchronized the extension, platform minimum, lifecycle/plan mappings, business documentation, release gate, tests, and release manifest at `0.5.166`; built `dist/ltjt-order-assistant-0.5.166.zip` with SHA-256 `68aeda857f0bf596eed3c5012fb37c6292977935ff215ce1d133983a8dffe259`.
- Archived the superseded `0.5.165` ZIP and its release manifest under `archive/releases/2026-09-03/`, with a non-current-history notice. No unique release artifact was deleted.
- Confirmed the current manually loaded unpacked/ZIP extension cannot silently replace itself. Chrome-supported unattended updates require either Chrome Web Store distribution or a same-key signed CRX delivered by HTTPS and installed through enterprise policy on Windows/macOS.
- Recommended an unlisted/private Chrome Web Store listing when the cloud PCs are unmanaged; if every PC is enrolled in AD/Azure AD, Chrome Enterprise Core, or another MDM, a self-hosted signed-CRX channel can instead use the project's server for `update.xml` and CRX publication.
- Deliberately did not add a nonfunctional in-extension downloader: an extension cannot install its own ZIP/CRX, remote executable code remains prohibited under Manifest V3, and the correct manifest, signing, publication, and policy design depends on the user's managed-device answer. Either supported route needs one final manual migration away from the existing unpacked installation.
- No ERP page, browser installation, extension runtime, signing key, Web Store listing, service, deployment, live task, or external system was changed.
## Verification
- Focused adaptive-entry regression: passed as part of the legacy suite.
- `node --check chrome-extension/ltjt-order-assistant/inpage.js`: passed.
- JSON parsing for the changed mappings and extension manifest: passed.
- `unzip -t dist/ltjt-order-assistant-0.5.166.zip`: passed; the archive contains the same 19 files as the governed extension source.
- `node --run check:repo`: 10/10 passed.
- `node --run check`: passed.
- `node --run test:control-plane`: 159/159 passed.
- `node --run test:legacy`: 269/269 passed.
- `node --run build`: passed.
- `check_project_docs.py`: passed.
- `check_doc_drift.py --task-id 20260903-adaptive-wait-auto-update-7b3e9a2c`: passed.
- `git diff --check`: passed.
- Full verification used a temporary symlink to the existing dependency tree in the isolated worktree; the symlink was removed afterward and is not part of the task output.
## Follow-ups
- Integrate and deploy/reload `0.5.166` only under separate authorization. Until then, the running browser extension remains unchanged, and this release still requires the existing manual installation procedure.
- Ask whether all target cloud PCs are enterprise-managed. After that answer, implement exactly one supported unattended-update channel: Web Store publication for unmanaged PCs, or same-key signed CRX + HTTPS update manifest + managed install policy for enterprise-managed PCs.
- For either channel, let Chrome own installation and periodic updates. An optional client action may call `chrome.runtime.requestUpdateCheck()` and report availability, but it must not force-reload the extension while an ERP task is active.
## Promotion Candidates
- Target documents: release/distribution architecture, operator deployment guidance, and the extension release decision record.
- Proposed durable fact: unpacked extensions are development installations and cannot be silently self-updated; production unattended updates must use a Chrome-supported Web Store or enterprise-policy signed-CRX channel, preserve Manifest V3's no-remote-code boundary, and avoid reloading during an active ERP operation.
- Evidence: Chrome's official extension distribution, self-hosting, update lifecycle, and Manifest V3 migration documentation; this task's source/package synchronization and full regression results.
- Future-task impact: release automation must retain one stable extension identity and signing authority, publish monotonically increasing versions, expose a recoverable rollback path, and treat the one-time migration from unpacked installs as an operator-controlled rollout.
- Human confirmation required: choose unmanaged/Web Store versus enterprise-managed/self-hosted distribution and identify who owns the stable extension identity/signing credentials. No secret or identity should be generated implicitly.
@@ -0,0 +1,66 @@
# Task: Integrate extension updates into local Windows service
## Identity
- Task ID: 20260903-service-extension-update-8d42c6f1
- Mode: Feature
- Branch: codex/20260903-service-extension-update-8d42c6f1-service-extension-update
- Worktree: /Users/inmanx/Documents/lwltAPI-service-extension-update-8d42c6f1
- Base commit: 500034bb6305c56271bc32918cb0edc885dbba44
- Owner: codex
- Status: Ready for Integration
## Scope
- Extend the existing browser-extension heartbeat so the separate central Node service compares the loaded browser version with one approved OSS release, coordinates an idle-only update across multiple accounts on each Windows Server, and verifies the new live browser version afterward.
- Keep update orchestration inside the current control-plane service and use Alibaba Cloud ECS Cloud Assistant as the existing remote execution boundary; do not introduce a separately maintained LTJT updater process on each host.
- Preserve the current unpacked-extension installation model and converge every Chrome profile on one shared `C:\ProgramData\LTJT\chrome-extension\ltjt-order-assistant` source directory. Do not claim that unmanaged Windows Chrome can install a self-hosted CRX.
## Intent And Constraints
- Current source already reports `chrome.runtime.getManifest().version` through the platform page to `/api/connections/heartbeat`, where `browser_connections.extension_version` stores it. This is a browser-originated heartbeat, not a server-side Windows filesystem probe.
- An authenticated administrator may publish an approved versioned ZIP. The service must validate bounded ZIP entries and Windows-safe paths, Manifest identity/runtime wiring, a monotonically newer version and SHA-256; store a content-addressed private OSS object; issue only a short-lived HMAC download capability; stage it, retain one rollback copy, and replace only an explicitly configured ProgramData extension directory.
- Never update or reload while an ERP execution is active, accepted, write-started, submitted, uncertain, or awaiting reconciliation. The server must withhold execution readiness during a required update and require a post-reload heartbeat at the target version before declaring success.
- The first bootstrap extension release must know how to prove idle state and request an idle reload after the service has replaced its local files. Existing `0.5.166` and older profiles require one final manual move/load from the shared ProgramData directory before automatic publication is enabled.
- Do not inspect `.env` or secrets, invent signing credentials, write to OSS, call Alibaba Cloud APIs, replace local extension files, reload Chrome, restart/deploy services, access ERP, or mutate live tasks during repository implementation and tests.
- Feature mode owns only this task record and task implementation files; canonical release/update architecture remains an Integration Gate promotion candidate.
## Outcome
- Added migration `019_extension_host_updates`: non-admin accounts can bind an ECS region/instance pair; private extension releases and one host-level update state per organization/instance persist in PostgreSQL. Required-migration readiness now includes `019`.
- Added default-off production configuration for extension publication, bounded package size, shared Windows install path, Cloud Assistant timeout/polling and a separately scoped Alibaba Cloud ECS credential. Enabling the feature requires complete OSS/ECS configuration and HTTPS `APP_ORIGIN` in production.
- Added an administrator-only `/accounts` release panel and ECS host mapping controls. Release publication validates the ZIP before storage, rejects unsafe/duplicate/encrypted/symlink paths and incorrect Manifest wiring, rejects downgrade or same-version/different-hash publication, stores a SHA-addressed private OSS object, records an audit event, and exposes no OSS credential or object URL.
- Added short-lived HMAC package downloads through the control plane. The service re-reads the private OSS object and verifies its stored byte count and SHA-256 before returning it; diagnostics replace the capability-bearing URL path with `:token`.
- Added the official Alibaba Cloud ECS SDK integration for one-shot `RunPowerShellScript` commands (`KeepCommand=false`). The command is bounded below the documented 24 KB Base64 limit, runs only under the configured `ProgramData\LTJT` subtree, refuses downgrades, verifies package SHA-256 and Manifest name/version, stages the new directory, keeps `.previous`, rolls back a failed switch, and emits a required completion marker.
- Made Cloud Assistant dispatch crash- and ambiguity-safe: each persisted attempt reconstructs the same signed download URL and 64-character `ClientToken`; an unknown API outcome remains `running` and reuses the same attempt instead of launching a second command. The absolute command deadline survives service restarts, definite failures retry at most three total attempts, and an already-started older release finishes before the host jumps directly to the newest active release.
- Extended the browser heartbeat with the extension's in-memory and durable safety proof. The server independently checks every account mapped to the same ECS instance for active leases, accepted/running ERP attempts, reconciliation tasks, and recent unsafe browser workers under the same organization lock used by task claiming. Whichever operation wins the lock blocks the other, so a new ERP execution cannot race file deployment.
- Added a second server-side claim gate against the current active release. A browser below the target version cannot receive a new ERP task when the update is waiting, running, deployed, unconfigured or failed; a target-version heartbeat is required before normal execution resumes. Existing unfinished host states also remain blocking if the feature is disabled during rollout.
- Added extension `0.5.167` safety/reload protocol and platform handling. The background worker rejects reload while any task is running, has crossed `write_started/submitted/uncertain`, or awaits reconciliation; after deployment the platform requests `chrome.runtime.reload()`, refreshes the page, and the next target-version heartbeat verifies the host. Multiple profiles sharing one host are reloaded and version-gated independently while sharing one deployment.
- Preserved `0.5.166`'s immediate-first, conditional 100 ms ERP readiness wait with no fixed fast-path delay. Synchronized the extension source, platform minimum, mappings, release gate, regression assertions and `dist/release-manifest.json` at `0.5.167`.
- Built `dist/ltjt-order-assistant-0.5.167.zip` with SHA-256 `6822ec660097a8889da8ea4fa22d4091467aa022067bff3bee2ac5406864b679`. Archived the superseded `0.5.166` ZIP and matching manifest under `archive/releases/2026-09-03/`; no unique historical release was discarded.
- Documented the central-server/multi-Windows-host topology, network boundary, RAM least-privilege requirement, account-to-instance grouping, initial bootstrap and future publication flow in `control-plane/README.md` and the extension README.
- No `.env` or secret was inspected; no OSS object was written, Alibaba Cloud API called, Windows directory replaced, Chrome runtime reloaded, service deployed/restarted, ERP accessed, or live task mutated.
## Verification
- `npm test`: passed (`test:control-plane` 166/166; `test:legacy` 270/270).
- `npm run check:repo`: 10/10 passed, including exact extension ZIP/source file comparison and release-manifest hash verification.
- `npm run build`: passed.
- Focused extension-update tests cover numeric version ordering, ZIP identity/unsafe Windows path rejection, HMAC tamper/expiry, ProgramData/hash/staging/rollback/no-downgrade script boundaries, Cloud Assistant terminal status/completion marker handling, and default-off production configuration.
- `npm audit --omit=dev`: reported 7 inherited findings (4 high, 3 moderate) in the pre-existing Fastify/static/AJV/ExcelJS dependency paths; the new Alibaba Cloud SDK path was not among the reported vulnerable paths. No unrelated dependency upgrade or audit fix was applied in this Feature task.
## Follow-ups
- Integration/deployment remains separately authorized: merge this feature, back up and apply migration `019`, configure the restricted RAM identity and OSS/HTTPS values, then restart the central service. None of those live actions occurred here.
- Before setting `EXTENSION_AUTO_UPDATE_ENABLED=true`, manually place/load bootstrap `0.5.167` from the shared ProgramData path in every existing Windows/Chrome profile and confirm its heartbeat. This is the last per-profile manual rollout; `0.5.166` cannot safely bootstrap the new protocol itself.
- Validate Cloud Assistant Agent status and central `APP_ORIGIN` HTTPS reachability on one non-production Windows Server, publish a higher test version, and observe waiting → running → deployed → reload → verified before widening the ECS account mappings.
- Address the inherited npm audit findings in a separately scoped dependency-security task; they were present in the base lockfile paths and are not specific to extension updating.
## Promotion Candidates
- Target documents: canonical system architecture, release/distribution decision record, current-state snapshot, and production operations guidance.
- Proposed durable fact: the production topology has one separate central control plane and multiple Alibaba ECS Windows Server browser hosts. The control plane owns version publication and state; private OSS owns immutable package bytes; ECS Cloud Assistant supplies one-shot host execution; each Chrome profile reports the actually loaded version and performs its own safe runtime reload.
- Proposed safety invariant: a host update and an ERP task claim use the same organization serialization boundary; no update starts while any mapped account is active or uncertain, and no old-version browser receives a new ERP execution while a higher activity release is required.
- Proposed rollout invariant: `0.5.167` is the one-time unpacked-extension bootstrap in the shared ProgramData directory. Every later release is monotonic, content-addressed and hash-verified, retains one rollback directory, retries only definite failures up to three attempts, and is accepted only after a target-version browser heartbeat.
- Evidence: migration/config/source/tests and synchronized `0.5.167` release artifact from this task; official Chrome Windows distribution constraints and Alibaba Cloud `RunCommand`/`DescribeInvocationResults` contracts.
- Human confirmation required: production RAM policy/resource scope, the exact ECS account mappings, the bootstrap completion checkpoint, and authorization to migrate/restart/publish or execute a real Cloud Assistant canary.