env
env 提供 guest 无法自行观察、但应用 UI 确实需要的粗化宿主状态。v0.1 对所有应用使用同一封闭 schema 和精度,不因信任档位返回不同字段。
基本示例
let environment = await host.env.snapshot();
applyTheme(environment.colorScheme);
host.events.on('env.change', async ({ changedFields }) => {
if (!changedFields.includes('colorScheme')) return;
environment = await host.env.snapshot();
applyTheme(environment.colorScheme);
});
变化事件只告诉 guest 哪些字段失效;重新读取快照可以避免多个字段来自不同时刻。
适用场景
- 深浅色主题、粗化语言和当前 UTC offset。
- 无障碍偏好,如减少动态效果或提高对比度。
设备型号、User-Agent、CPU/GPU、内存、序列号、字体枚举、精确网络类型和稳定硬件标识不属于 env。
L1 边界
宿主独占的是操作系统/壳层当前提供给本应用的主题、语言、时区偏移和无障碍偏好。guest 无法从自身计算可靠取得这些状态;主题系统、翻译资源和响应式布局仍由 guest 实现。
能力声明
{
"capabilities": ["host:env.snapshot"],
"events": ["env.change"]
}
Reference
- env.snapshot()
- env.change event
env.snapshot() -> EnvironmentSnapshot
event env.change {
changedFields: EnvironmentField[]
}
EnvironmentSnapshot {
colorScheme: "light" | "dark"
locale: {
language: ascii-lowercase[2..8]
script?: ascii-titlecase[4]
}
timeZoneOffsetMinutes: i16
accessibility: {
reducedMotion: boolean
increasedContrast: boolean
}
}
EnvironmentField = "colorScheme" | "locale" | "timeZoneOffsetMinutes"
| "accessibility"
timeZoneOffsetMinutes 是当前本地时间相对 UTC 的分钟差,向最接近的 15 分钟取整并钳制到 [-840, 840];不返回时区名称。locale 不含地区、变体或扩展。绘图面安全区域属于 canvas.getInfo(),避免在环境快照里暗含“主绘图面”。
原生 WASM 示例
EnvironmentSnapshot env = host_env_snapshot();
ui_set_dark_mode(env.color_scheme == COLOR_DARK);
ui_set_reduced_motion(env.accessibility.reduced_motion);
字符串通过有界 UTF-8 绑定返回。宿主无法规范化字段时整个 snapshot() 以 unavailable 失败,不能把浏览器原始字符串或规范外枚举穿透给 guest。
精度规则
- locale 固定只保留语言和可选文字;时区固定为粗化 UTC offset。
- 颜色方案和无障碍布尔偏好属于用户与本应用的直接 UI 上下文。
事件与生命周期
- 尚未交付的
change可以合并多个字段和重复变化;合并结果是其间所有失效字段的集合。 - guest 不应从事件次数推断用户行为。
- 应用恢复前台时,后台期间的变化可以合并为一次综合失效通知。
snapshot()必须线性化:在调用开始与返回之间存在一个逻辑时点,返回的所有字段都等于该时点状态。字段在该点之后变化时,若已声明env.change,对应失效事件必须在快照返回后仍可送达,不能被这次读取吞掉。
安全与预算
- 信任档位:green;入向 flow 如实标记,provenance 为
app-context。 - 字段集合封闭;新增高熵字段必须进入新版本并重新做指纹评审。
- v0.1 预算键为
env.snapshotsPerMinute和env.changesPerMinute。 - 不提供可用来构造高精度计时器的时间戳。
- 宿主不得为追踪目的故意制造每应用不同的环境值。
错误与测试
env.snapshot 无法形成完整封闭快照时以 unavailable 失败,不得捏造默认值。一致性测试至少覆盖主题切换、语言/时区粗化、后台恢复、事件合并和未知平台值。