feat: establish native desktop update trust root
This commit is contained in:
parent
a2302cfd13
commit
cff488bb03
29 changed files with 8485 additions and 60 deletions
|
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"schema": "hololake.native-desktop-trust-root-receipt/v1",
|
||||||
|
"receipt_id": "HLP-NATIVE-DESKTOP-TRUST-ROOT-001-20260812",
|
||||||
|
"development_id": "DEV-20260811-010",
|
||||||
|
"repository_id": "REPO-014",
|
||||||
|
"branch": "main",
|
||||||
|
"source_base_commit": "a2302cfd13c45d25b0cb1f70e49b05d957a71e31",
|
||||||
|
"canonical_source": "product-source/hololake-native-desktop",
|
||||||
|
"recorded_at": "2026-08-12T10:27:13+08:00",
|
||||||
|
"implemented": {
|
||||||
|
"clean_tauri_v2_rust_react_scaffold": true,
|
||||||
|
"inherited_product_tree_copied": false,
|
||||||
|
"upstream_product_update_endpoints_present": false,
|
||||||
|
"release_trust_default": "UNPROVISIONED_FAIL_CLOSED",
|
||||||
|
"tauri_static_manifest_field_compatibility": true,
|
||||||
|
"human_opt_in_download_install_required": true,
|
||||||
|
"automatic_update_check_on_startup": false,
|
||||||
|
"automatic_restart_allowed": false,
|
||||||
|
"updater_ipc_exposed_to_webview": false,
|
||||||
|
"private_signing_material_in_source": false,
|
||||||
|
"product_ui_started": false
|
||||||
|
},
|
||||||
|
"verification": {
|
||||||
|
"foundation_contract_tests": "PASS_4_OF_4",
|
||||||
|
"architecture_projection_tests": "PASS_4_OF_4",
|
||||||
|
"rust_unit_tests": "PASS_3_OF_3",
|
||||||
|
"rust_strict_clippy": "PASS_100",
|
||||||
|
"typescript_and_vite_build": "PASS_100",
|
||||||
|
"tauri_release_binary_build_without_bundle": "PASS_100",
|
||||||
|
"npm_production_dependency_audit": "PASS_0_VULNERABILITIES",
|
||||||
|
"git_diff_check": "PASS_100"
|
||||||
|
},
|
||||||
|
"truth_boundary": {
|
||||||
|
"local_source_implemented": true,
|
||||||
|
"release_binary_built": true,
|
||||||
|
"installer_bundle_built": false,
|
||||||
|
"formal_bundle_identifier_registered": false,
|
||||||
|
"production_update_domain_registered": false,
|
||||||
|
"tauri_update_signing_key_provisioned": false,
|
||||||
|
"platform_signed_and_notarized": false,
|
||||||
|
"installed_runtime_accepted": false,
|
||||||
|
"published_to_remote_main": false,
|
||||||
|
"deployed": false
|
||||||
|
},
|
||||||
|
"next_gate": "REGISTER_PRODUCTION_IDENTITY_OR_CONTINUE_DUAL_DONOR_AUDIT_FROM_THIS_FAIL_CLOSED_BASELINE",
|
||||||
|
"state": "LOCAL_CHECKPOINT_VERIFIED_NOT_PUBLISHED"
|
||||||
|
}
|
||||||
13
product-source/hololake-native-desktop/.gitignore
vendored
Normal file
13
product-source/hololake-native-desktop/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
/dist/
|
||||||
|
/node_modules/
|
||||||
|
/src-tauri/target/
|
||||||
|
/src-tauri/gen/
|
||||||
|
*.tsbuildinfo
|
||||||
|
/vite.config.js
|
||||||
|
/vite.config.d.ts
|
||||||
|
*.key
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
*.mobileprovision
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
# HoloLake Native Desktop
|
# HoloLake Native Desktop
|
||||||
|
|
||||||
状态:`FOUNDATION_ROOT_CREATED · TAURI_SCAFFOLD_PENDING`
|
状态:`MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED`
|
||||||
|
|
||||||
这是 HoloLake 唯一未来桌面产品主线的干净源码根。它将采用 Tauri v2、Rust 和
|
这是 HoloLake 唯一未来桌面产品主线的干净源码根。它将采用 Tauri v2、Rust 和
|
||||||
React/TypeScript,但不会从现有 Tauri 或 Electron 目录整树复制。
|
React/TypeScript,但不会从现有 Tauri 或 Electron 目录整树复制。
|
||||||
|
|
||||||
当前只登记产品边界和发布广播合同。选择并验收新的视觉/交互方向之前,不创建会意外继承
|
当前已经建立可编译的最小 Tauri 工程、默认关闭联网的发布信任根,以及兼容 Tauri 静态更新
|
||||||
任一旧应用布局的产品 UI。
|
清单的 HoloLake 发布广播合同。选择并验收新的视觉/交互方向之前,不创建会意外继承任一旧
|
||||||
|
应用布局的产品 UI;当前窗口只显示基础状态,不代表产品界面方向。
|
||||||
|
|
||||||
## 供体边界
|
## 供体边界
|
||||||
|
|
||||||
|
|
@ -33,4 +34,4 @@ React/TypeScript,但不会从现有 Tauri 或 Electron 目录整树复制。
|
||||||
1. 确认正式 bundle identifier、HoloLake 更新域名和密钥托管责任;
|
1. 确认正式 bundle identifier、HoloLake 更新域名和密钥托管责任;
|
||||||
2. 完成双供体功能/数据/许可证/安全审计;
|
2. 完成双供体功能/数据/许可证/安全审计;
|
||||||
3. 选择新的人类界面视觉方向;
|
3. 选择新的人类界面视觉方向;
|
||||||
4. 再生成最小 Tauri 工程和第一条知识纵向切片。
|
4. 在选定视觉方向后实现第一条知识纵向切片。
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"$id": "https://releases.hololake.invalid/contracts/release-broadcast.schema.json",
|
"$id": "urn:hololake:release-broadcast:v1",
|
||||||
"title": "HoloLake signed opt-in release broadcast",
|
"title": "HoloLake signed opt-in release broadcast",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
|
|
@ -8,12 +8,10 @@
|
||||||
"schema",
|
"schema",
|
||||||
"releaseId",
|
"releaseId",
|
||||||
"version",
|
"version",
|
||||||
"publishedAt",
|
"pub_date",
|
||||||
"features",
|
"notes",
|
||||||
"compatibility",
|
|
||||||
"restart",
|
|
||||||
"platforms",
|
"platforms",
|
||||||
"rollback"
|
"hololake"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"schema": { "const": "hololake.release-broadcast/v1" },
|
"schema": { "const": "hololake.release-broadcast/v1" },
|
||||||
|
|
@ -22,61 +20,69 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
|
"pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
|
||||||
},
|
},
|
||||||
"publishedAt": { "type": "string", "format": "date-time" },
|
"pub_date": { "type": "string", "format": "date-time" },
|
||||||
"features": {
|
"notes": { "type": "string", "minLength": 1 },
|
||||||
"type": "array",
|
|
||||||
"minItems": 1,
|
|
||||||
"items": { "type": "string", "minLength": 1 }
|
|
||||||
},
|
|
||||||
"fixes": {
|
|
||||||
"type": "array",
|
|
||||||
"items": { "type": "string", "minLength": 1 }
|
|
||||||
},
|
|
||||||
"compatibility": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["minimumVersion", "dataMigrationRequired"],
|
|
||||||
"properties": {
|
|
||||||
"minimumVersion": { "type": "string", "minLength": 1 },
|
|
||||||
"dataMigrationRequired": { "type": "boolean" },
|
|
||||||
"notes": { "type": "string" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"restart": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": ["required", "automaticAllowed"],
|
|
||||||
"properties": {
|
|
||||||
"required": { "const": true },
|
|
||||||
"automaticAllowed": { "const": false },
|
|
||||||
"message": { "type": "string" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"platforms": {
|
"platforms": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": ["url", "size", "sha256", "tauriSignature"],
|
"required": ["url", "signature", "size", "sha256"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"url": { "type": "string", "pattern": "^https://" },
|
"url": { "type": "string", "format": "uri", "pattern": "^https://" },
|
||||||
"size": { "type": "integer", "minimum": 1 },
|
"size": { "type": "integer", "minimum": 1 },
|
||||||
"sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
"sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
|
||||||
"tauriSignature": { "type": "string", "minLength": 1 },
|
"signature": { "type": "string", "minLength": 1 },
|
||||||
"platformCodeSignatureReceipt": { "type": "string", "minLength": 1 },
|
"platformCodeSignatureReceipt": { "type": "string", "minLength": 1 },
|
||||||
"notarizationReceipt": { "type": "string", "minLength": 1 }
|
"notarizationReceipt": { "type": "string", "minLength": 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollback": {
|
"hololake": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": ["supported", "healthReceiptRequired"],
|
"required": ["features", "compatibility", "restart", "rollback"],
|
||||||
"properties": {
|
"properties": {
|
||||||
"supported": { "const": true },
|
"features": {
|
||||||
"healthReceiptRequired": { "const": true },
|
"type": "array",
|
||||||
"previousVersion": { "type": "string" }
|
"minItems": 1,
|
||||||
|
"items": { "type": "string", "minLength": 1 }
|
||||||
|
},
|
||||||
|
"fixes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": { "type": "string", "minLength": 1 }
|
||||||
|
},
|
||||||
|
"compatibility": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["minimumVersion", "dataMigrationRequired"],
|
||||||
|
"properties": {
|
||||||
|
"minimumVersion": { "type": "string", "minLength": 1 },
|
||||||
|
"dataMigrationRequired": { "type": "boolean" },
|
||||||
|
"notes": { "type": "string" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"restart": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["required", "automaticAllowed"],
|
||||||
|
"properties": {
|
||||||
|
"required": { "const": true },
|
||||||
|
"automaticAllowed": { "const": false },
|
||||||
|
"message": { "type": "string" }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rollback": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": ["supported", "healthReceiptRequired"],
|
||||||
|
"properties": {
|
||||||
|
"supported": { "const": true },
|
||||||
|
"healthReceiptRequired": { "const": true },
|
||||||
|
"previousVersion": { "type": "string" }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,19 @@
|
||||||
{
|
{
|
||||||
"schema": "hololake.native-desktop-foundation/v1",
|
"schema": "hololake.native-desktop-foundation/v1",
|
||||||
"record_id": "HLP-NATIVE-DESKTOP-FOUNDATION-001",
|
"record_id": "HLP-NATIVE-DESKTOP-FOUNDATION-001",
|
||||||
"state": "FOUNDATION_ROOT_CREATED_TAURI_SCAFFOLD_PENDING",
|
"state": "MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED",
|
||||||
"canonical_shell": "TAURI_V2_RUST_REACT",
|
"canonical_shell": "TAURI_V2_RUST_REACT",
|
||||||
"product_ui_implementation_started": false,
|
"product_ui_implementation_started": false,
|
||||||
"selected_visual_direction_present": false,
|
"selected_visual_direction_present": false,
|
||||||
"upstream_product_update_endpoints": [],
|
"upstream_product_update_endpoints": [],
|
||||||
"production_update_endpoint_owner": "HOLOLAKE_ONLY",
|
"production_update_endpoint_owner": "HOLOLAKE_ONLY",
|
||||||
"release_broadcast_contract": "contracts/release-broadcast.schema.json",
|
"release_broadcast_contract": "contracts/release-broadcast.schema.json",
|
||||||
|
"release_trust_source": "src-tauri/release-trust.json",
|
||||||
|
"release_trust_state": "UNPROVISIONED_FAIL_CLOSED",
|
||||||
|
"tauri_update_artifacts_enabled": true,
|
||||||
|
"automatic_update_check_on_startup": false,
|
||||||
|
"human_opt_in_download_install_required": true,
|
||||||
|
"automatic_restart_allowed": false,
|
||||||
"private_signing_material_allowed_in_source": false,
|
"private_signing_material_allowed_in_source": false,
|
||||||
"donors": [
|
"donors": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
12
product-source/hololake-native-desktop/index.html
Normal file
12
product-source/hololake-native-desktop/index.html
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>HoloLake</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2462
product-source/hololake-native-desktop/package-lock.json
generated
Normal file
2462
product-source/hololake-native-desktop/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
28
product-source/hololake-native-desktop/package.json
Normal file
28
product-source/hololake-native-desktop/package.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "hololake-native-desktop",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"test": "node --test scripts/*.test.mjs",
|
||||||
|
"tauri": "tauri"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tauri-apps/api": "2.10.1",
|
||||||
|
"@tauri-apps/plugin-process": "2.3.1",
|
||||||
|
"@tauri-apps/plugin-updater": "2.10.0",
|
||||||
|
"react": "^19.2.0",
|
||||||
|
"react-dom": "^19.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tauri-apps/cli": "2.10.0",
|
||||||
|
"@types/react": "^19.2.7",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"@vitejs/plugin-react": "^5.1.1",
|
||||||
|
"typescript": "~5.9.3",
|
||||||
|
"vite": "^7.3.5",
|
||||||
|
"vitest": "^4.0.18"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
import fs from 'node:fs'
|
||||||
|
import path from 'node:path'
|
||||||
|
import test from 'node:test'
|
||||||
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
||||||
|
const readJson = (relative) => JSON.parse(fs.readFileSync(path.join(root, relative), 'utf8'))
|
||||||
|
const readText = (relative) => fs.readFileSync(path.join(root, relative), 'utf8')
|
||||||
|
|
||||||
|
const foundation = readJson('foundation.json')
|
||||||
|
const trust = readJson('src-tauri/release-trust.json')
|
||||||
|
const tauriConfig = readJson('src-tauri/tauri.conf.json')
|
||||||
|
const capability = readJson('src-tauri/capabilities/default.json')
|
||||||
|
const broadcast = readJson('contracts/release-broadcast.schema.json')
|
||||||
|
|
||||||
|
test('clean Tauri foundation contains no inherited product updater endpoint', () => {
|
||||||
|
assert.deepEqual(foundation.upstream_product_update_endpoints, [])
|
||||||
|
assert.deepEqual(trust.endpoints, [])
|
||||||
|
assert.deepEqual(trust.allowedReleaseHosts, [])
|
||||||
|
assert.equal(trust.state, 'UNPROVISIONED_FAIL_CLOSED')
|
||||||
|
assert.equal(trust.publicKey, '')
|
||||||
|
for (const relative of [
|
||||||
|
'foundation.json',
|
||||||
|
'src-tauri/release-trust.json',
|
||||||
|
'src-tauri/tauri.conf.json',
|
||||||
|
'src-tauri/src/release_trust.rs',
|
||||||
|
]) {
|
||||||
|
const source = readText(relative)
|
||||||
|
assert.doesNotMatch(source, /refactoringhq|tolaria|outline/i)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('release activation remains explicitly human controlled', () => {
|
||||||
|
assert.equal(trust.automaticCheckOnStartup, false)
|
||||||
|
assert.equal(trust.automaticDownload, false)
|
||||||
|
assert.equal(trust.humanOptInInstallRequired, true)
|
||||||
|
assert.equal(trust.automaticRestart, false)
|
||||||
|
assert.equal(foundation.automatic_update_check_on_startup, false)
|
||||||
|
assert.equal(foundation.human_opt_in_download_install_required, true)
|
||||||
|
assert.equal(foundation.automatic_restart_allowed, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Tauri can emit signed updater artifacts without exposing updater IPC', () => {
|
||||||
|
assert.equal(tauriConfig.bundle.createUpdaterArtifacts, true)
|
||||||
|
assert.deepEqual(capability.permissions, ['core:default'])
|
||||||
|
assert.equal(capability.permissions.includes('updater:default'), false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('broadcast remains Tauri-compatible and carries HoloLake human metadata', () => {
|
||||||
|
const platform = broadcast.properties.platforms.additionalProperties
|
||||||
|
assert.equal(platform.required.includes('signature'), true)
|
||||||
|
assert.equal(platform.required.includes('url'), true)
|
||||||
|
assert.equal(broadcast.required.includes('pub_date'), true)
|
||||||
|
assert.equal(broadcast.required.includes('publishedAt'), false)
|
||||||
|
assert.equal(broadcast.required.includes('notes'), true)
|
||||||
|
assert.equal(broadcast.required.includes('hololake'), true)
|
||||||
|
assert.equal(
|
||||||
|
broadcast.properties.hololake.properties.restart.properties.automaticAllowed.const,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
})
|
||||||
5415
product-source/hololake-native-desktop/src-tauri/Cargo.lock
generated
Normal file
5415
product-source/hololake-native-desktop/src-tauri/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
26
product-source/hololake-native-desktop/src-tauri/Cargo.toml
Normal file
26
product-source/hololake-native-desktop/src-tauri/Cargo.toml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
[package]
|
||||||
|
name = "hololake-native-desktop"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "HoloLake native desktop foundation"
|
||||||
|
authors = ["HoloLake"]
|
||||||
|
license = "AGPL-3.0-or-later"
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.77.2"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "hololake_native_desktop_lib"
|
||||||
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tauri-build = { version = "2.5.4", features = [] }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
tauri = { version = "=2.10.2", features = [] }
|
||||||
|
tauri-runtime = "=2.10.0"
|
||||||
|
tauri-runtime-wry = "=2.10.0"
|
||||||
|
tauri-plugin-updater = "2.10.0"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile = "3"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
tauri_build::build()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "../gen/schemas/desktop-schema.json",
|
||||||
|
"identifier": "default",
|
||||||
|
"description": "Minimum HoloLake desktop foundation; updater actions are not exposed to the webview yet.",
|
||||||
|
"windows": ["main"],
|
||||||
|
"permissions": ["core:default"]
|
||||||
|
}
|
||||||
BIN
product-source/hololake-native-desktop/src-tauri/icons/icon.png
Normal file
BIN
product-source/hololake-native-desktop/src-tauri/icons/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"schema": "hololake.release-trust/v1",
|
||||||
|
"state": "UNPROVISIONED_FAIL_CLOSED",
|
||||||
|
"endpoints": [],
|
||||||
|
"publicKey": "",
|
||||||
|
"allowedReleaseHosts": [],
|
||||||
|
"automaticCheckOnStartup": false,
|
||||||
|
"automaticDownload": false,
|
||||||
|
"humanOptInInstallRequired": true,
|
||||||
|
"automaticRestart": false
|
||||||
|
}
|
||||||
12
product-source/hololake-native-desktop/src-tauri/src/lib.rs
Normal file
12
product-source/hololake-native-desktop/src-tauri/src/lib.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
mod release_trust;
|
||||||
|
|
||||||
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
pub fn run() {
|
||||||
|
tauri::Builder::default()
|
||||||
|
.setup(|app| {
|
||||||
|
release_trust::install_updater_if_provisioned(app.handle())?;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("failed to run HoloLake native desktop");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
hololake_native_desktop_lib::run();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tauri::{AppHandle, Runtime, Url};
|
||||||
|
use tauri_plugin_updater::UpdaterExt;
|
||||||
|
|
||||||
|
const EMBEDDED_RELEASE_TRUST: &str = include_str!("../release-trust.json");
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
|
struct ReleaseTrust {
|
||||||
|
schema: String,
|
||||||
|
state: TrustState,
|
||||||
|
endpoints: Vec<String>,
|
||||||
|
public_key: String,
|
||||||
|
allowed_release_hosts: Vec<String>,
|
||||||
|
automatic_check_on_startup: bool,
|
||||||
|
automatic_download: bool,
|
||||||
|
human_opt_in_install_required: bool,
|
||||||
|
automatic_restart: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||||
|
enum TrustState {
|
||||||
|
UnprovisionedFailClosed,
|
||||||
|
Provisioned,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ValidatedReleaseTrust {
|
||||||
|
Disabled,
|
||||||
|
Enabled {
|
||||||
|
endpoints: Vec<Url>,
|
||||||
|
public_key: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_release_trust(raw: &str) -> Result<ValidatedReleaseTrust, String> {
|
||||||
|
let trust: ReleaseTrust = serde_json::from_str(raw)
|
||||||
|
.map_err(|error| format!("invalid HoloLake release trust document: {error}"))?;
|
||||||
|
|
||||||
|
if trust.schema != "hololake.release-trust/v1" {
|
||||||
|
return Err("unsupported HoloLake release trust schema".into());
|
||||||
|
}
|
||||||
|
if trust.automatic_check_on_startup || trust.automatic_download || trust.automatic_restart {
|
||||||
|
return Err("automatic check, download and restart must remain disabled".into());
|
||||||
|
}
|
||||||
|
if !trust.human_opt_in_install_required {
|
||||||
|
return Err("human opt-in installation is required".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
match trust.state {
|
||||||
|
TrustState::UnprovisionedFailClosed => {
|
||||||
|
if !trust.endpoints.is_empty()
|
||||||
|
|| !trust.public_key.is_empty()
|
||||||
|
|| !trust.allowed_release_hosts.is_empty()
|
||||||
|
{
|
||||||
|
return Err(
|
||||||
|
"unprovisioned trust must not contain endpoint or public key material".into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(ValidatedReleaseTrust::Disabled)
|
||||||
|
}
|
||||||
|
TrustState::Provisioned => {
|
||||||
|
if trust.endpoints.len() != 1 {
|
||||||
|
return Err("exactly one HoloLake release endpoint is required".into());
|
||||||
|
}
|
||||||
|
if trust.public_key.trim().is_empty() {
|
||||||
|
return Err("the HoloLake updater public key is required".into());
|
||||||
|
}
|
||||||
|
if trust.allowed_release_hosts.len() != 1 {
|
||||||
|
return Err("exactly one HoloLake-owned release host is required".into());
|
||||||
|
}
|
||||||
|
let allowed_host = trust.allowed_release_hosts[0].trim();
|
||||||
|
if allowed_host.is_empty() || allowed_host.contains('/') || allowed_host.contains(':') {
|
||||||
|
return Err("the HoloLake release host must be a bare DNS name".into());
|
||||||
|
}
|
||||||
|
let endpoint = Url::parse(&trust.endpoints[0])
|
||||||
|
.map_err(|error| format!("invalid HoloLake release endpoint: {error}"))?;
|
||||||
|
if endpoint.scheme() != "https" {
|
||||||
|
return Err("the HoloLake release endpoint must use HTTPS".into());
|
||||||
|
}
|
||||||
|
if endpoint.host_str() != Some(allowed_host) {
|
||||||
|
return Err(
|
||||||
|
"the updater endpoint is not owned by the configured HoloLake host".into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(ValidatedReleaseTrust::Enabled {
|
||||||
|
endpoints: vec![endpoint],
|
||||||
|
public_key: trust.public_key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install_updater_if_provisioned<R: Runtime>(
|
||||||
|
app: &AppHandle<R>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
match validate_release_trust(EMBEDDED_RELEASE_TRUST)? {
|
||||||
|
ValidatedReleaseTrust::Disabled => Ok(()),
|
||||||
|
ValidatedReleaseTrust::Enabled {
|
||||||
|
endpoints,
|
||||||
|
public_key,
|
||||||
|
} => {
|
||||||
|
let updater = tauri_plugin_updater::Builder::new()
|
||||||
|
.pubkey(public_key)
|
||||||
|
.build();
|
||||||
|
app.plugin(updater)?;
|
||||||
|
app.updater_builder().endpoints(endpoints)?.build()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{validate_release_trust, ValidatedReleaseTrust};
|
||||||
|
|
||||||
|
fn document(state: &str, endpoint: &str, public_key: &str, allowed_host: &str) -> String {
|
||||||
|
format!(
|
||||||
|
r#"{{
|
||||||
|
"schema":"hololake.release-trust/v1",
|
||||||
|
"state":"{state}",
|
||||||
|
"endpoints":[{endpoint}],
|
||||||
|
"publicKey":"{public_key}",
|
||||||
|
"allowedReleaseHosts":[{allowed_host}],
|
||||||
|
"automaticCheckOnStartup":false,
|
||||||
|
"automaticDownload":false,
|
||||||
|
"humanOptInInstallRequired":true,
|
||||||
|
"automaticRestart":false
|
||||||
|
}}"#
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unprovisioned_document_disables_update_networking() {
|
||||||
|
let trust =
|
||||||
|
validate_release_trust(&document("UNPROVISIONED_FAIL_CLOSED", "", "", "")).unwrap();
|
||||||
|
assert!(matches!(trust, ValidatedReleaseTrust::Disabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accepts_https_shape_but_rejects_insecure_endpoints() {
|
||||||
|
let owned_shape = document(
|
||||||
|
"PROVISIONED",
|
||||||
|
"\"https://releases.example.test/latest.json\"",
|
||||||
|
"public",
|
||||||
|
"\"releases.example.test\"",
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
validate_release_trust(&owned_shape).is_ok(),
|
||||||
|
"endpoint ownership is additionally checked by release provisioning"
|
||||||
|
);
|
||||||
|
let insecure = document(
|
||||||
|
"PROVISIONED",
|
||||||
|
"\"http://releases.example.test/latest.json\"",
|
||||||
|
"public",
|
||||||
|
"\"releases.example.test\"",
|
||||||
|
);
|
||||||
|
assert!(validate_release_trust(&insecure).is_err());
|
||||||
|
let mismatched_host = document(
|
||||||
|
"PROVISIONED",
|
||||||
|
"\"https://upstream.example.test/latest.json\"",
|
||||||
|
"public",
|
||||||
|
"\"releases.example.test\"",
|
||||||
|
);
|
||||||
|
assert!(validate_release_trust(&mismatched_host).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rejects_automatic_or_nonconsensual_install_policy() {
|
||||||
|
let automatic = document("UNPROVISIONED_FAIL_CLOSED", "", "", "")
|
||||||
|
.replace("\"automaticDownload\":false", "\"automaticDownload\":true");
|
||||||
|
assert!(validate_release_trust(&automatic).is_err());
|
||||||
|
let no_opt_in = document("UNPROVISIONED_FAIL_CLOSED", "", "", "").replace(
|
||||||
|
"\"humanOptInInstallRequired\":true",
|
||||||
|
"\"humanOptInInstallRequired\":false",
|
||||||
|
);
|
||||||
|
assert!(validate_release_trust(&no_opt_in).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
|
"productName": "HoloLake",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"identifier": "world.guanghu.hololake",
|
||||||
|
"build": {
|
||||||
|
"frontendDist": "../dist",
|
||||||
|
"devUrl": "http://127.0.0.1:5210",
|
||||||
|
"beforeDevCommand": "npm run dev",
|
||||||
|
"beforeBuildCommand": "npm run build"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"windows": [
|
||||||
|
{
|
||||||
|
"label": "main",
|
||||||
|
"title": "HoloLake",
|
||||||
|
"width": 1180,
|
||||||
|
"height": 760,
|
||||||
|
"minWidth": 760,
|
||||||
|
"minHeight": 520
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"security": {
|
||||||
|
"csp": "default-src 'self'; connect-src 'self' ipc: http://ipc.localhost; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bundle": {
|
||||||
|
"active": true,
|
||||||
|
"targets": "all",
|
||||||
|
"createUpdaterArtifacts": true,
|
||||||
|
"category": "Productivity"
|
||||||
|
}
|
||||||
|
}
|
||||||
24
product-source/hololake-native-desktop/src/main.tsx
Normal file
24
product-source/hololake-native-desktop/src/main.tsx
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function FoundationScreen() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<p className="eyebrow">HoloLake Native Desktop</p>
|
||||||
|
<h1>新的光湖桌面主线正在建立信任根</h1>
|
||||||
|
<p>
|
||||||
|
当前只完成最小 Tauri 外壳与更新安全边界。知识工作区将在双供体审计和视觉方向确定后开始。
|
||||||
|
</p>
|
||||||
|
<dl>
|
||||||
|
<div><dt>上游更新</dt><dd>已关闭</dd></div>
|
||||||
|
<div><dt>光湖发布广播</dt><dd>等待正式端点与公钥</dd></div>
|
||||||
|
<div><dt>下载与安装</dt><dd>必须由人类选择</dd></div>
|
||||||
|
</dl>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
<StrictMode><FoundationScreen /></StrictMode>,
|
||||||
|
)
|
||||||
16
product-source/hololake-native-desktop/src/styles.css
Normal file
16
product-source/hololake-native-desktop/src/styles.css
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
:root {
|
||||||
|
font-family: ui-sans-serif, system-ui, sans-serif;
|
||||||
|
color: #eaf0ff;
|
||||||
|
background: #07101f;
|
||||||
|
font-synthesis: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body { margin: 0; min-width: 320px; min-height: 100vh; }
|
||||||
|
main { max-width: 720px; margin: 0 auto; padding: 12vh 32px; }
|
||||||
|
.eyebrow { color: #82a7ff; letter-spacing: .08em; text-transform: uppercase; }
|
||||||
|
h1 { font-size: clamp(2rem, 5vw, 4rem); line-height: 1.05; }
|
||||||
|
p { color: #b7c5e5; line-height: 1.7; }
|
||||||
|
dl { margin-top: 48px; border-top: 1px solid #263554; }
|
||||||
|
dl div { display: flex; justify-content: space-between; gap: 24px; padding: 16px 0; border-bottom: 1px solid #263554; }
|
||||||
|
dt { color: #8fa4cf; }
|
||||||
|
dd { margin: 0; text-align: right; }
|
||||||
20
product-source/hololake-native-desktop/tsconfig.app.json
Normal file
20
product-source/hololake-native-desktop/tsconfig.app.json
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
7
product-source/hololake-native-desktop/tsconfig.json
Normal file
7
product-source/hololake-native-desktop/tsconfig.json
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
12
product-source/hololake-native-desktop/vite.config.ts
Normal file
12
product-source/hololake-native-desktop/vite.config.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
clearScreen: false,
|
||||||
|
server: {
|
||||||
|
host: '127.0.0.1',
|
||||||
|
port: 5210,
|
||||||
|
strictPort: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
>
|
>
|
||||||
> 决议:`ADR-0178`
|
> 决议:`ADR-0178`
|
||||||
>
|
>
|
||||||
> 状态:`CURRENT_CANONICAL · CLEAN_SOURCE_NOT_YET_SCAFFOLDED · MIGRATION_NOT_COMPLETE`
|
> 状态:`CURRENT_CANONICAL · MINIMAL_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED · MIGRATION_NOT_COMPLETE`
|
||||||
|
|
||||||
## 1 · 最终判定
|
## 1 · 最终判定
|
||||||
|
|
||||||
|
|
@ -136,10 +136,11 @@ Electron 本身不会自动带来更完整的知识库,但当前 Electron 实
|
||||||
|
|
||||||
## 8 · 仍未完成
|
## 8 · 仍未完成
|
||||||
|
|
||||||
- 新目录尚未脚手架化;
|
- 新目录已形成可编译的最小 Tauri 脚手架和默认不联网的更新信任根,但尚未形成产品 UI;
|
||||||
- HoloLake 更新域名、签名密钥托管和开发者证书尚未登记;
|
- HoloLake 更新域名、签名密钥托管和开发者证书尚未登记;
|
||||||
- 双供体完整功能矩阵、许可证清单、数据迁移图和安全威胁模型尚未完成;
|
- 双供体完整功能矩阵、许可证清单、数据迁移图和安全威胁模型尚未完成;
|
||||||
- 新 UI 视觉方向尚未由冰朔选择;
|
- 新 UI 视觉方向尚未由冰朔选择;
|
||||||
- 不存在可发布的新主线安装包。
|
- 不存在可发布的新主线安装包。
|
||||||
|
|
||||||
所以当前事实是:**框架和迁移方法已经纠正,开发基线尚待从干净根开始建立。**
|
所以当前事实是:**框架和迁移方法已经纠正,干净开发基线已经建立;生产发布身份、完整供体
|
||||||
|
审计、视觉选择与产品纵向切片仍未完成。**
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
"schema": "hololake.canonical-desktop-shell/v2",
|
"schema": "hololake.canonical-desktop-shell/v2",
|
||||||
"record_id": "HLP-CANONICAL-DESKTOP-SHELL-001",
|
"record_id": "HLP-CANONICAL-DESKTOP-SHELL-001",
|
||||||
"version": "2026-08-12.2",
|
"version": "2026-08-12.2",
|
||||||
"state": "CURRENT_CANONICAL_FOUNDATION_ROOT_CREATED_TAURI_SCAFFOLD_PENDING",
|
"state": "CURRENT_CANONICAL_MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED",
|
||||||
"development_id": "DEV-20260811-010",
|
"development_id": "DEV-20260811-010",
|
||||||
"decision": {
|
"decision": {
|
||||||
"canonical_shell": "TAURI_V2_RUST_REACT",
|
"canonical_shell": "TAURI_V2_RUST_REACT",
|
||||||
"canonical_source": "product-source/hololake-native-desktop",
|
"canonical_source": "product-source/hololake-native-desktop",
|
||||||
"canonical_source_state": "FOUNDATION_ROOT_CREATED_TAURI_SCAFFOLD_PENDING",
|
"canonical_source_state": "MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED",
|
||||||
"existing_tauri_source": "product-source/hololake-platform",
|
"existing_tauri_source": "product-source/hololake-platform",
|
||||||
"existing_tauri_role": "READ_ONLY_ENGINEERING_CAPABILITY_DONOR_AND_ACCEPTANCE_ORACLE",
|
"existing_tauri_role": "READ_ONLY_ENGINEERING_CAPABILITY_DONOR_AND_ACCEPTANCE_ORACLE",
|
||||||
"electron_role": "READ_ONLY_KNOWLEDGE_UX_BEHAVIOR_DONOR_AND_ACCEPTANCE_ORACLE",
|
"electron_role": "READ_ONLY_KNOWLEDGE_UX_BEHAVIOR_DONOR_AND_ACCEPTANCE_ORACLE",
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
},
|
},
|
||||||
"update_route": {
|
"update_route": {
|
||||||
"record_id": "HLP-SIGNED-OPT-IN-UPDATE-001",
|
"record_id": "HLP-SIGNED-OPT-IN-UPDATE-001",
|
||||||
"state": "ARCHITECTURE_ACCEPTED_IMPLEMENTATION_NOT_STARTED",
|
"state": "FAIL_CLOSED_LOCAL_TRUST_ROOT_IMPLEMENTED_PRODUCTION_IDENTITY_UNPROVISIONED",
|
||||||
"upstream_product_update_endpoints_allowed": false,
|
"upstream_product_update_endpoints_allowed": false,
|
||||||
"hololake_owned_https_endpoint_only": true,
|
"hololake_owned_https_endpoint_only": true,
|
||||||
"release_broadcast_may_arrive_automatically": true,
|
"release_broadcast_may_arrive_automatically": true,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ test("HoloLake has one clean canonical desktop destination", () => {
|
||||||
assert.equal(shell.decision.canonical_source, "product-source/hololake-native-desktop");
|
assert.equal(shell.decision.canonical_source, "product-source/hololake-native-desktop");
|
||||||
assert.equal(
|
assert.equal(
|
||||||
shell.decision.canonical_source_state,
|
shell.decision.canonical_source_state,
|
||||||
"FOUNDATION_ROOT_CREATED_TAURI_SCAFFOLD_PENDING",
|
"MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED",
|
||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
shell.decision.existing_tauri_role,
|
shell.decision.existing_tauri_role,
|
||||||
|
|
@ -85,14 +85,22 @@ test("HoloLake owns an opt-in signed update route", () => {
|
||||||
assert.deepEqual(foundation.upstream_product_update_endpoints, []);
|
assert.deepEqual(foundation.upstream_product_update_endpoints, []);
|
||||||
assert.equal(foundation.production_update_endpoint_owner, "HOLOLAKE_ONLY");
|
assert.equal(foundation.production_update_endpoint_owner, "HOLOLAKE_ONLY");
|
||||||
assert.equal(foundation.private_signing_material_allowed_in_source, false);
|
assert.equal(foundation.private_signing_material_allowed_in_source, false);
|
||||||
assert.equal(broadcastSchema.properties.restart.properties.required.const, true);
|
assert.equal(
|
||||||
assert.equal(broadcastSchema.properties.restart.properties.automaticAllowed.const, false);
|
broadcastSchema.properties.hololake.properties.restart.properties.required.const,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
broadcastSchema.properties.hololake.properties.restart.properties.automaticAllowed.const,
|
||||||
|
false,
|
||||||
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
broadcastSchema.properties.platforms.additionalProperties.properties.url.pattern,
|
broadcastSchema.properties.platforms.additionalProperties.properties.url.pattern,
|
||||||
/^\^https:/,
|
/^\^https:/,
|
||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
broadcastSchema.properties.platforms.additionalProperties.required.includes("tauriSignature"),
|
broadcastSchema.properties.platforms.additionalProperties.required.includes("signature"),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
assert.equal(broadcastSchema.required.includes("pub_date"), true);
|
||||||
|
assert.equal(broadcastSchema.required.includes("publishedAt"), false);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@
|
||||||
"adr": "product-source/hololake-platform/docs/adr/0178-tauri-canonical-shell-and-electron-capability-donor.md",
|
"adr": "product-source/hololake-platform/docs/adr/0178-tauri-canonical-shell-and-electron-capability-donor.md",
|
||||||
"canonical_shell": "TAURI_V2_RUST_REACT",
|
"canonical_shell": "TAURI_V2_RUST_REACT",
|
||||||
"canonical_source": "product-source/hololake-native-desktop",
|
"canonical_source": "product-source/hololake-native-desktop",
|
||||||
"canonical_source_state": "FOUNDATION_ROOT_CREATED_TAURI_SCAFFOLD_PENDING",
|
"canonical_source_state": "MINIMAL_TAURI_SCAFFOLD_AND_FAIL_CLOSED_UPDATE_TRUST_ROOT_IMPLEMENTED",
|
||||||
"existing_tauri_role": "READ_ONLY_ENGINEERING_CAPABILITY_DONOR_AND_ACCEPTANCE_ORACLE",
|
"existing_tauri_role": "READ_ONLY_ENGINEERING_CAPABILITY_DONOR_AND_ACCEPTANCE_ORACLE",
|
||||||
"electron_role": "READ_ONLY_KNOWLEDGE_UX_BEHAVIOR_DONOR_AND_ACCEPTANCE_ORACLE",
|
"electron_role": "READ_ONLY_KNOWLEDGE_UX_BEHAVIOR_DONOR_AND_ACCEPTANCE_ORACLE",
|
||||||
"parallel_product_lines_allowed": false,
|
"parallel_product_lines_allowed": false,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue