DSH / Atlas
2026-09-14implementedtesting

Isolate installed-update materials from releases and user data

将安装版更新物料与发布及用户数据隔离

An installed-update walkthrough needs two increasing versions with a shared application identity. Reusing normal release paths can expose test metadata to unrelated clients, while storing test state inside an installation directory loses evidence during replacement. A successful copy does not establish that a signed installer exists.

English

Problem

An installed-update walkthrough needs two increasing versions with a shared application identity. Reusing normal release paths can expose test metadata to unrelated clients, while storing test state inside an installation directory loses evidence during replacement. A successful copy does not establish that a signed installer exists.

Decision

Version derivation follows the release version reference; this record continues to govern material, application identity, and user-data isolation.

The material preparer accepts a retained test-only manifest with a random identity and distribution namespace. It copies a verified source runtime into separate derived test versions, changes only release-family versions and matching dependency references, and seals and verifies both inventories. The original runtime is verified again and its descriptor hash must remain unchanged. Existing output directories are not overwritten; a failed copy retains a failure record and cannot create a completion receipt.

The generated bootstrap validates the installed package identity before importing production main. Each version assigns the same application-data subdirectory to its test Electron profile, Harness home, and external journals. Environment values inherited from the first launch do not determine those paths. The manifest reader rejects changed test destinations, identities, and directory locations. The operator guide distinguishes source preparation, private runtime copies, and signed installed-app qualification.

The journal decision and local updater qualification decision remain active: material preparation neither proves an installed upgrade nor changes hardware authorization. Signing, upload, installation, and network mutation are absent from these preparation tools.

Alternatives considered

Retag the repository's package manifests between builds. That changes the working release version and can affect other tasks or release commands. Private runtime copies and package-specific metadata keep the source checkout's versions unchanged.

Use the production identity or terminal-only data overrides. Production identity shares registration and data with ordinary installs; terminal overrides may not survive installer-triggered startup. A private identity and packaged bootstrap retain isolation across versions.

Resume by overwriting a partially prepared version. That can mix source generations and discard failure evidence. An existing output or preparation record refuses reuse; a clean attempt requires a new run.

Infer upload failure from a denied bucket-configuration query. Object access and bucket configuration have separate permissions. An added preflight can reject credentials whose object operations work. Diagnose the exact API and compare existing successful evidence before asking for broader permissions; no attempted PUT means no observed upload failure.

Consequences

Feed publication reuses a completed binary-upload result whose retained plan exactly matches the current verified distribution, including run identity, version, destinations, sizes, and hashes. It records the receipt and plan hashes and reads only the feed remotely. Initial binary upload retains full public-byte verification. Repeating that transfer for every feed write adds latency and traffic without changing immutable artifacts; the retained receipt establishes prior delivery, not a guarantee against later external deletion. Missing, failed, or mismatched receipts refuse publication rather than silently triggering another large download.

The separate publication entry defaults to local receipt and byte verification. Binary upload cannot advertise a version; successor feed publication requires original-version startup evidence and a matching previous feed. The test-only transport disables SDK write retries, requires an authoritative unversioned-bucket check before immutable-object protection, and verifies exact public bytes. A local lock does not provide distributed exclusion: one operator must own the mutable feed across machines. Each authorized operation retains independent stage records; uncertain writes require inspection, not automatic repetition. Matching objects can be reconciled without replacement. In-memory sequencing and substituted HTTP transport tests do not establish real COS publication or installed-app startup.

The separate operator packaging entry checks the durable signing interlock before loading credentials and rechecks after interactive confirmation. Each execution owns one version and a never-reused packaging directory. It uses the existing supervisor with a 15-minute stage deadline, retains redacted output and selected source/tool hashes, and compares those inputs after building. Upload credentials never reach the builder; publication and installation are absent. Inert subprocess tests cover refusal, redaction, retained failure, and no reuse; actual signed output and package verification remain separate evidence. An overall deadline cannot limit CSP-internal PIN attempts or authorize unattended signing.

Application preparation freezes built main/preload modules, renderer files, and the generated bootstrap once per run, records SHA-256 values, and rejects changed, missing, or additional frozen files. The qualification builder configuration reuses the ordinary configuration factory with the selected private runtime, so resource verification and signing use the same runtime version. It preserves installer hooks and publisher checks while selecting a shared test identity, package entry, and fixed test feed. Dependency trees and build tools remain separate mutable inputs and require final-build records. Configuration validation uses the pinned builder with a substituted signer, not hardware or installed-app evidence.

The read-only distribution planner checks each version's generated YAML against local installer bytes and separates immutable binary objects from one mutable feed URL. It reconstructs feed fields from validated values instead of preserving arbitrary input fields. The output explicitly carries file-integrity-only status and no publication authority; credentials, signatures, package identity, and version 1 startup are outside this check.

The separate signature reader requires the real updater verifier, valid Authenticode and timestamp attributes, and unchanged executable bytes. It runs verification children with scrubbed credentials and without inherited PowerShell module paths; incompatible module overrides cannot be treated as successful verification. The publisher comes from the trusted public certificate rather than remote YAML. Read-only verification never calls SignTool, accesses the signing token, or executes the inspected file. Signature success cannot establish package contents or a completed installation.

The package verifier extracts the signed installer itself rather than trusting a neighboring unpacked directory. Its archived identity, update configuration, frozen application files, and Harness runtime must match the retained run, and its mandatory test policy must be valid. It reads runtime files from ASAR, accepts only electron-builder's dependency-manifest transformation, and checks executable signatures in app.asar.unpacked. Unsigned runtime executable changes cannot pass through a regenerated inventory alone. Independent immutable records preserve each check's stages and failures. Final input hashes prevent an installer/feed change from inheriting an earlier result. Real ASAR and runtime fixtures cover mismatches while substituting only external verification and archive processes; actual signed packages still require their own receipts. Installer registration and installed-app behavior are outside this file inspection and remain operator checks.

The network fault procedure binds a program-specific outbound rule to the verified original executable hash and random run identity. It rejects changed bytes before creation and after confirmation, and removes only a matching owned rule. Recovery remains available if the executable disappears. The operator controls both mutations; stages persist before and after each operation, and failures stop without retry. Firewall-cmdlet substitutes exercise the real script, but a rule's recorded presence or absence never proves traffic interruption or successful download recovery. Adapter-wide or VPN changes are excluded because they can disconnect the operator's remote control.

Generated-entry tests execute both versions with only Electron's path API substituted and verify the shared directories before main imports. Runtime tests verify dependency retagging, unchanged third-party versions and source bytes, refusal of damaged input, and retained partial failures. Copies consume extra disk space. Source preparation can boot the source runtime, but copied-version startup, final package contents, signatures, publication, and installation require separate evidence; completion receipts name those limits rather than inferring success.

中文

问题

安装版更新演练需要两个递增版本共用应用身份。复用正常发布路径可能向无关客户端暴露测试元数据,而把测试状态放在安装目录中会在替换时丢失证据。复制成功不能证明已有签名安装包。

决策

版本派生遵循发布版本说明;本记录继续规定物料、应用身份和用户数据的隔离。

物料准备器接受保留的 test 专用清单,其中包含随机身份和分发命名空间。它将已验证的原始运行时复制为独立的派生测试版本,仅修改发布家族版本和匹配的依赖引用,再生成并验证两个完整性清单。原始运行时再次验证,其描述文件哈希必须保持不变。已有输出目录不被覆盖;复制失败保留失败记录,不能生成完成回执。

生成的启动入口在导入生产主程序前验证已安装包身份。两个版本将相同的应用数据子目录用于测试 Electron profile、Harness home 和外部日志。首次启动继承的环境变量不决定这些路径。清单读取器拒绝已改变的 test 目标、身份和目录位置。人工指南区分源码准备、独立运行时副本和签名安装版验收。

日志决策与本地 updater 验收决策继续有效:物料准备既不证明已安装应用升级通过,也不改变硬件授权。这些准备工具不包含签名、上传、安装或网络改动。

考虑过的替代方案

在两次构建之间修改仓库包清单的版本。 这会改变工作区发布版本,可能影响其他任务或发布命令。独立运行时副本与包专属元数据保持源码工作区版本不变。

使用生产身份或仅通过终端覆盖数据目录。 生产身份与普通安装共享注册和数据;终端覆盖不一定在安装器触发启动时保留。独立身份与包内启动入口维持跨版本隔离。

覆盖准备到一半的版本来继续执行。 这可能混合不同源码代际并丢弃失败证据。已有输出或准备记录拒绝复用;全新尝试需要新批次。

从桶配置查询被拒绝推断上传失败。 对象访问与桶配置使用不同权限。新增前置检查可能拒绝对象操作原本可用的凭据。申请扩大权限前,先定位准确 API 并对照已有成功证据;没有尝试 PUT,就没有观察到上传失败。

结果

feed 发布复用已完成的二进制上传结果,其保留计划必须与当前已验证分发计划完全匹配,包括批次身份、版本、目标地址、大小和哈希。发布记录回执及计划哈希,仅在远端读取 feed。首次二进制上传保留完整公网字节验证。每次写 feed 都重复传输会增加延迟和流量,却不改变不可变物料;保留回执证明此前分发成功,不保证对象此后未被外部删除。回执缺失、失败或不匹配时拒绝发布,不隐式触发另一次大文件下载。

独立的发布入口默认仅验证本地回执与字节。二进制上传不能公布版本;后继版本 feed 发布要求原版本启动证据及匹配的旧 feed。test 专用传输禁用 SDK 写入重试,在使用不可变对象保护前要求权威查询确认存储桶未启用版本控制,并验证准确的公网字节。本地锁不提供分布式排他:必须由一个操作者跨机器独占可变 feed。每次授权操作保留独立阶段记录;写入结果不确定时要求检查,不能自动重试。匹配对象可核对而不替换。内存顺序测试和替代 HTTP 传输测试不证明真实 COS 发布或已安装应用启动通过。

独立的人工打包入口在加载凭据前检查持久签名保护锁,并在交互确认后再次检查。每次执行只拥有一个版本和一个不复用的打包目录。它使用现有监督程序与 15 分钟阶段期限,保留脱敏输出和选定的源码/工具哈希,并在构建后比较这些输入。上传凭据绝不传给构建器;入口不包含发布和安装。无功能子进程测试覆盖拒绝、脱敏、失败保留与不复用;实际签名产物和包验证仍需独立证据。整体期限不能限制 CSP 内部 PIN 尝试,也不能授权无人值守签名。

应用准备按批次冻结一次已构建的主程序/预加载模块、界面文件和生成的启动入口,记录 SHA-256,并拒绝冻结文件被修改、缺失或额外增加。验收打包配置将选定的独立运行时传给常规配置工厂,使资源校验与签名使用同一运行时版本。它保留安装器钩子和发布者检查,同时选择共享测试身份、包入口和固定 test feed。依赖树和构建工具仍是独立的可变输入,需要最终构建记录。配置验证使用固定版本构建器和替代签名器,不是硬件或已安装应用证据。

只读分发规划器逐版本核对生成的 YAML 与本地安装包字节,并将不可变二进制对象与一个可变 feed URL 分开。它从已验证的值重建 feed 字段,不保留任意输入字段。输出明确标识仅验证文件完整性、没有发布授权;凭据、签名、包身份与版本 1 启动不属于本检查。

独立的签名读取器要求真实 updater 验签、有效 Authenticode 与时间戳属性,以及未变的可执行文件字节。验签子进程移除凭据和继承的 PowerShell 模块路径;不兼容模块覆盖不能被当作验签成功。发布者来自可信公钥证书,而非远端 YAML。只读检查绝不调用 SignTool、访问签名令牌或执行被检查文件。签名通过不能证明包内容或安装完成。

安装包检查器解开签名安装包本身,而非信任相邻的解包目录。归档内身份、更新配置、冻结应用文件和 Harness 运行时必须与保留批次一致,测试强更策略也必须有效。检查器从 ASAR 读取运行时文件,只接受 electron-builder 对依赖 manifest 的转换,并在 app.asar.unpacked 中检查可执行文件签名。未签名的运行时可执行文件变化不能仅靠重新生成清单就通过。独立且不可覆盖的记录保留每次检查的阶段与失败。最终输入哈希防止安装包/feed 变化继承旧结果。真实 ASAR 和运行时夹具覆盖不符情况,仅替换外部验签和归档进程;实际签名包仍需各自回执。安装器注册和已安装应用行为不属于文件检查,保留为人工检查项。

网络故障步骤将指定程序的出站规则绑定到已验证原版本可执行文件哈希及随机批次身份。它在创建前和确认后拒绝变化的字节,仅移除匹配的自有规则。可执行文件消失后仍可恢复。两次改动均由操作者控制;每次操作前后持久记录阶段,失败即停、不重试。防火墙命令替身执行真实脚本,但记录规则存在或不存在绝不证明流量中断或下载恢复成功。不改网卡或 VPN,因为这可能断开操作者的远控。

生成入口测试只替换 Electron 路径 API,执行两个版本并在主程序导入前核对共享目录。运行时测试验证依赖版本替换、第三方版本和原始字节不变、损坏输入拒绝以及失败现场保留。副本额外占用磁盘。源码准备可启动原始运行时,但副本版本启动、最终包内容、签名、发布和安装均需独立证据;完成回执说明这些局限,不推断成功。