diff --git a/docs/en/reference/contracts/component.md b/docs/en/reference/contracts/component.md index 80a9afd..e52e713 100644 --- a/docs/en/reference/contracts/component.md +++ b/docs/en/reference/contracts/component.md @@ -4,6 +4,8 @@ The package `schemaVersion` and `hostApiMajor` are 1; the current SDK is 0.1.2, ## Runtime compatibility +Interface deprecation and retirement follow the [SDK compatibility policy](../modules/development.md#sdk-compatibility-and-interface-retirement). + Component `version` orders work updates, SDK versions identify development and diagnostic releases, `schemaVersion` identifies manifest structure, and `hostApiMajor` identifies the interface and behavior generation. SDK releases need not match exactly. Published contracts stay compatible within a generation; cross-generation support covers only explicitly implemented and verified generations. Currently only manifest schema 1 and API generation 1 are supported for installation and execution. Optional `requiredFeatures` defaults to an empty array. It contains at most 256 unique, case-sensitive identifiers, each 1–128 ASCII letters, digits, dots, underscores or hyphens, matching the host handshake feature catalog. Unknown well-formed identifiers are missing mandatory features; malformed or duplicate entries are invalid manifests. Require only essential functionality. Probe optional features and degrade gracefully. Denied capabilities do not make a component version incompatible and do not prevent enabling it. Breaking changes to existing feature semantics require a new API generation; an SDK version increment alone is insufficient. diff --git a/docs/en/reference/modules/development.md b/docs/en/reference/modules/development.md index 5a2f5ff..bc39a86 100644 --- a/docs/en/reference/modules/development.md +++ b/docs/en/reference/modules/development.md @@ -8,7 +8,7 @@ Read the [local development lessons](../../guide/lessons.md), [recipes](../../re ## Author SDK versioning -The author SDK is not locked. Its current version is `0.1.2`, independently using `major.minor.patch`. `sdkVersion` in the host protocol is the current version source. Keep JavaScript, declarations, machine protocol, host distribution, examples and both guide editions synchronized when the SDK changes. +SDK releases evolve independently under the compatibility policy below. The current version is `0.1.2`, independently using `major.minor.patch`. `sdkVersion` in the host protocol is the current version source. Keep JavaScript, declarations, machine protocol, host distribution, examples and both guide editions synchronized when the SDK changes. During `0.x`, increment patch for routine additions and fixes, including limited protocol adjustments such as content tags. Increment minor and reset patch only when the user explicitly decides to enter a new SDK feature stage. Document affected methods, types, events and required author changes for any break. Starting at `1.0.0`, increment major for incompatible changes, minor for compatible additions and patch for fixes; reset all fields to the right. Use the highest-impact change once per SDK delivery. Host UI, internal refactoring, packaging and prose-only changes do not automatically change the SDK version. Different distributed SDK content must not reuse a version; comment/format-only changes are excluded. @@ -17,3 +17,31 @@ During `0.x`, increment patch for routine additions and fixes, including limited The application separately uses four fields (`major.minor.patch.revision`). Development uploads retain the previous default application's version. Only after an explicit decision to update Steam default is the release version incremented once, based on all changes since the previous default, followed by validation, develop upload and default promotion. This does not automatically increment the SDK. Component requirements and enabled-intent recovery follow [runtime compatibility](../contracts/component.md#runtime-compatibility). + +## SDK compatibility and interface retirement + +### Compatibility within a generation + +Preserve published interfaces and behavior within the same `hostApiMajor/apiMajor`, including during `0.x`. SDK version changes, refactoring, maintenance cost and usage levels do not justify removing an interface. Compatible additions retain existing calls and introduce stable feature identifiers. Fixes restore the published contract rather than changing valid calls. + +Removing methods, types or events, changing arguments, results, authorization, data ownership or cancellation semantics, or narrowing published valid inputs, budgets or guarantees is a breaking change. Increment the affected API generation and follow the retirement conditions. SDK version increments cannot replace API generation changes. Cross-generation support covers only explicitly implemented, documented and verified ranges; there is no automatic previous-generation or perpetual multi-generation promise. A generation still advertised as supported must retain its published interfaces. + +### Deprecation and permanent retirement + +Deprecation recommends migration while the interface remains callable and truthfully advertised. When declaring an actual deprecation, mark declarations with `@deprecated`, supply a replacement and migration guide, and stop using the old interface in new templates. Deprecation does not automatically expire an interface. + +Ordinary permanent retirement requires all of the following: + +1. A replacement, migration guide, and runnable test host and SDK are available to authors, identifying affected methods, types, events and widget impact. +2. A public deprecation announcement identifies scope, migration and earliest retirement conditions. Count at least 90 complete days from the latest availability of the announcement and all materials above. +3. At least two distinct Steam `default` releases after that starting point provide advance notices describing impact and migration. `develop` uploads, repeat uploads, documentation-only updates and the release performing retirement do not count as advance notices. Both elapsed time and release count must be satisfied, whichever is later. +4. Verify that blocking old widgets preserves installation data and enabled intent, with automatic recovery when compatibility returns. Revocation, uninstall and later user disable actions take precedence; never restore revoked grants or deleted data. +5. The user explicitly decides to retire the affected generation in a specified `default` release. Synchronize supported ranges, contracts, SDK, messages and verification. Elapsed time or a `develop` upload does not authorize retirement. + +Expanded retirement scope or an incompatible migration target requires renewed notice and grace for the new impact; compatible fixes that preserve the migration contract do not restart the period. A next-generation test host may enable migration before the new `default` release; dual-generation execution in the production host is not required. Without verified cross-generation support, block old widgets under [runtime compatibility](../contracts/component.md#runtime-compatibility), showing plain widget incompatibility rather than interface diagnostics. + +### Serious security vulnerability exception + +A confirmed serious security vulnerability may require immediate blocking of affected features without the ordinary grace period. Explain scope and reason, preserve unaffected data and enabled intent, check the block at execution and final delivery, and do not advertise blocked features as usable. Recovery still respects revocation, uninstall and current user intent. Cost, refactoring and low usage do not qualify. A temporary security block does not itself satisfy ordinary permanent retirement conditions. + +No interfaces are currently declared deprecated or retired, and this policy introduces no security block or SDK, API-generation or format-version changes. diff --git a/docs/reference/contracts/component.md b/docs/reference/contracts/component.md index 363dd52..c0a98f1 100644 --- a/docs/reference/contracts/component.md +++ b/docs/reference/contracts/component.md @@ -6,6 +6,8 @@ ## 运行兼容性 +接口弃用、同代际兼容承诺及跨代际退役条件统一见[SDK 兼容与接口退役](../modules/development.md#sdk-兼容与接口退役)。 + 组件 `version` 只用于作品更新排序;SDK 发行版本只用于开发与诊断,不要求组件与宿主 SDK 精确匹配。`schemaVersion` 标识清单结构,`hostApiMajor` 标识接口及行为兼容代际,分别管理。同代际保持已发布契约兼容;跨代际仅支持明确实现并验证的范围。当前清单结构只支持 schemaVersion=1,运行接口代际只支持 hostApiMajor=1,不根据应用版本猜测支持范围。 清单可声明 `requiredFeatures` 字符串数组,缺省为空;最多256项,每项1–128个ASCII字母、数字、点、下划线或连字符,不允许重复。值精确匹配宿主握手 `features` 目录。只声明没有就无法运行的接口或特性;可选功能通过 `features` 探测并降级。未知的合法标识视为缺少必需功能,拒绝运行;类型、重复或格式错误属于无效清单。功能支持不等于授权,Capability 拒绝不构成版本不兼容,也不阻止启用。新增接口时为其登记稳定特性标识;改变既有接口或特性含义的破坏性变更必须提升接口代际,不能只修改 SDK 版本。 diff --git a/docs/reference/contracts/host-api.md b/docs/reference/contracts/host-api.md index b997cec..dd7a444 100644 --- a/docs/reference/contracts/host-api.md +++ b/docs/reference/contracts/host-api.md @@ -306,6 +306,8 @@ location需要独立声明与授权。网页使用标准 `getCurrentPosition` / ## 请求顺序与预算 +公开接口的兼容、弃用与退役遵循[SDK 兼容与接口退役](../modules/development.md#sdk-兼容与接口退役)。 + 协议变更遵循格式版本规则(宿主文档:`../development.md#格式版本兼容与迁移`)。features 返回支持的方法名及 `webassembly`、`location`、`events`、`context.visibility`、`request.cancel`、`directory.snapshot`、`network.safeRedirect`;实现支持不代表授权。features供作者探测支持情况并提供降级。所有Capability仍可拒绝。 解析前每 WebView 限 60 条/秒、突发 16 条,8 MiB/秒、突发 16 MiB;全宿主限 240 条/秒、突发 64 条,32 MiB/秒、突发 64 MiB。超额不解析、不回应不可信 ID,SDK 等待会超时;单条仍限 8 MiB。limits 返回这些值和并发、超时、正文、KV、目录额度。获取 WebView 原始消息的开销无法由预算消除。 diff --git a/docs/reference/modules/development.md b/docs/reference/modules/development.md index 9ce9d26..bbc3687 100644 --- a/docs/reference/modules/development.md +++ b/docs/reference/modules/development.md @@ -12,7 +12,7 @@ TypeScript使用ES2020、DOM、strict及noEmit,不启用skipLibCheck。HTTP头 ## 作者 SDK 版本管理 -作者 SDK 不锁定,当前为 `0.1.2`,采用独立的 `major.minor.patch` 三段版本。`sdk/protocol.json` 的 `sdkVersion` 是当前版本来源,`widget-host.js` 标头、类型声明、宿主分发及作者指南必须同步;SDK 版本不是宿主最低版本或权限授予依据。组件的接口代际、必需特性及不兼容处理统一见[运行兼容性](../contracts/component.md#运行兼容性)。 +作者 SDK 版本独立演进,兼容原则遵循下述固定规则;当前为 `0.1.2`,采用独立的 `major.minor.patch` 三段版本。`sdk/protocol.json` 的 `sdkVersion` 是当前版本来源,`widget-host.js` 标头、类型声明、宿主分发及作者指南必须同步;SDK 版本不是宿主最低版本或权限授予依据。组件的接口代际、必需特性及不兼容处理统一见[运行兼容性](../contracts/component.md#运行兼容性)。 | 阶段/变更 | 递增规则 | | --- | --- | @@ -25,6 +25,34 @@ TypeScript使用ES2020、DOM、strict及noEmit,不启用skipLibCheck。HTTP头 `hostApiMajor/apiMajor` 表示宿主接口兼容代际,`protocolVersion` 表示桥接信封/握手格式代际,包/布局/存档 `schemaVersion` 和内部状态格式分别管理;它们不跟随 SDK 数字自动递增。仅各自契约的代际变化才更新相关值并同步双方校验;兼容与迁移遵循格式版本规则(宿主文档:`../development.md#格式版本兼容与迁移`),仍须按上表递增 SDK 并说明作者影响。当前各格式均以 v1 为基线,分别管理。组件及布局 manifest.version 仍使用自己的三段版本,不改成应用四段版本。 +## SDK 兼容与接口退役 + +### 同代际兼容 + +同一 `hostApiMajor/apiMajor` 内保持已发布接口与行为兼容,`0.x` 也不例外;SDK 升版、内部重构、维护成本或使用量不能成为删除接口的依据。兼容新增保留旧调用,新增稳定特性标识;修复恢复已发布契约,不能以修复名义改变合法调用。 + +删除方法、类型或事件,改变参数、返回值、权限、数据归属、取消语义,或收紧已发布的合法输入、额度与保证,均按破坏性变更处理,递增受影响的接口代际,并遵守退役条件。SDK 自身的版本递增不能替代接口代际变化。跨代际只支持明确实现、登记并验证的范围,不自动承诺上一代或永久多代运行;仍承诺支持的代际不得静默缺失其已发布接口。 + +### 弃用与彻底退役 + +弃用表示建议迁移,接口仍可调用并如实列入支持范围;实际宣布弃用时,在类型声明标注 `@deprecated`,提供替代接口和迁移说明,新模板停止使用旧接口。弃用不等于退役,不因时间经过自动失效。 + +普通接口彻底退役必须同时满足以下条件: + +1. 替代接口、迁移指南以及作者可获取并运行的测试宿主和 SDK 已提供,列明受影响方法、类型、事件与组件影响。 +2. 公开弃用公告说明影响范围、迁移方法和最早退役条件。以公告及前项全部材料均可获取的较晚时刻为起点,经过至少 90 个完整日。 +3. 起点之后至少两次不同的 Steam `default` 正式更新说明提前告知上述影响与迁移路径。`develop` 上传、重复上传、仅更新文档及执行退役的当次更新均不计为提前告知。时间和更新次数须同时满足,取较晚者。 +4. 验证旧组件被阻止运行时仍保留安装数据与启用意图,恢复兼容后自动恢复;撤权、卸载及用户后续停用仍具有优先级,不恢复已撤销授权或已清理数据。 +5. 用户明确决定在指定的 `default` 发布中退役相关代际,并同步支持范围、协议、SDK、提示和验证。满足期限或上传 `develop` 均不自动授权退役。 + +扩大退役范围或更换不兼容的迁移目标时,对新增影响重新公告并计算期限;不改变迁移契约的兼容修复不重置期限。可先提供下一代测试宿主供迁移,再在满足条件后发布新的 `default`;不要求为此先在正式宿主实现双代运行。无已验证的跨代际实现时,旧组件按[运行兼容性](../contracts/component.md#运行兼容性)阻止启用,界面只说明组件不兼容,不展示接口诊断。 + +### 严重安全漏洞例外 + +确认存在严重安全漏洞时,可立即阻断受影响功能,无需等待普通宽限期;明确说明影响范围和原因,保留不受影响的数据及启用意图,实际执行和最终投递均检查阻断状态,特性声明不能继续宣称功能可用。恢复后仍遵循撤权、卸载和当前用户意图。维护成本、重构或低使用量不属于此例外;临时安全阻断本身不表示普通永久退役条件已满足。 + +当前没有宣布弃用或退役的接口,也没有依据本规则新增安全阻断;本节不修改 SDK、接口代际或格式版本。 + ## 身份与目录 开发页仅包含用户显式新建或添加已有项目得到的开发组件;普通本地导入、内置及工坊组件不会自动归入开发。宿主记录 `development:` 安装身份,新增遵循全局widgetId去重(宿主文档:`../architecture.md#身份与数据归属`),不因更换目录或来源绕过;包声明不能自行指定来源。 diff --git a/host-snapshot.json b/host-snapshot.json index 8caad39..542efcf 100644 --- a/host-snapshot.json +++ b/host-snapshot.json @@ -22,8 +22,8 @@ { "source": "docs/contracts/component.md", "destination": "docs/reference/contracts/component.md", - "sourceSha256": "b53da2e32d741165b3861d4385f4d6557e51ac2fe6a683d0692cb33c8177f387", - "sha256": "3a6d65327fcb90a26398e4fd6ffcbe49ed862a62fb317f0f7cd5e15d166d4da0" + "sourceSha256": "71ca9a1376740b4780f096500270e2a3418363ec02c3be6012d713630b5eb6d2", + "sha256": "cf356d83f5bfa281b0252546a33e9b06cdcc791606f3637f2aef3013e8a07057" }, { "source": "docs/contracts/configuration.md", @@ -40,8 +40,8 @@ { "source": "docs/contracts/host-api.md", "destination": "docs/reference/contracts/host-api.md", - "sourceSha256": "c326bef73d001860b0c031715101a1c1fd953c0e3f7bd25632a3a55da7efbeab", - "sha256": "04d8e0a62290f77275170ab2dbdeca3de8e268c4e9685cbda0ee7864e5da78e0" + "sourceSha256": "226ae778e369f34b2d23e2e1a6fd94e45264b2b70ad28820b19f9697eef17367", + "sha256": "f628be738175c15cfd7aa1c1bbef69dfc2d95a2738221666f9c6c053b7f50675" }, { "source": "docs/contracts/layout.md", @@ -76,8 +76,8 @@ { "source": "docs/modules/development.md", "destination": "docs/reference/modules/development.md", - "sourceSha256": "d462a23796d987b014188a66be743a2cd1b03083b16460a3e0c6f967b05ba56e", - "sha256": "5e3c91193c2a7eb485a1d4be4c8c43d218f7aa6bf09469032c40dd2e13710e03" + "sourceSha256": "edad5400bd8d1bbfd9340221220ccfce376b5d7d95f42227ffde605a897219cf", + "sha256": "5aa44961756a0977324e1afa69b83e13e86ff3c17b36d23d72dd276f4059f8bf" }, { "source": "docs/modules/edge-garden.md", diff --git a/skills/widget-workshop-dev/SKILL.md b/skills/widget-workshop-dev/SKILL.md index d522324..e3ebc1b 100644 --- a/skills/widget-workshop-dev/SKILL.md +++ b/skills/widget-workshop-dev/SKILL.md @@ -19,6 +19,8 @@ The plugin root is two directories above this file. Resolve all paths from that ## API lookup and review +For SDK changes and migration advice, follow [SDK compatibility and interface retirement](../../docs/en/reference/modules/development.md#sdk-compatibility-and-interface-retirement). Do not infer compatibility or retirement from SDK version numbers alone. + Read docs/public/sdk/widget-host.d.ts for exact request/result types and docs/public/sdk/protocol.json for features and budgets. Read the relevant docs/en/reference contract before implementing a host call. Check authorization, ownership, expiry, cancellation and errors, not just argument types. The six capabilities are external.open, location, notifications, clipboard, directory.write and screen.capture; networking and documented base interfaces work without authorization. During review, trace asynchronous work through completion and cleanup; inspect denial/revocation, stale successes and failures, scoped resources, CAS saves, native hit regions and package contents. Lead with actionable defects, locations, consequences and repairs. Report only validation actually executed. Static checks are not actual WebView, input-device or multi-monitor tests.